一, 写两个线程, 一个线程打印 1-52, 另一个线程打印 A-Z, 打印顺序是 12A34B...5152Z.
1, 开始审题没审清楚, 所以写了一个三个线程版的程序:
测试类:
- public class Test
- {
- public static void main(String[] args) {
- PrintNumChar p=new PrintNumChar();
- MyRunnable my=new MyRunnable(p);
- Thread t1=new Thread(my,"A");
- Thread t2=new Thread(my,"B");
- Thread t3=new Thread(my,"C");
- t1.start();
- t2.start();
- t3.start();
- }
- }
打印类:
- public class PrintNumChar
- {
- // 定义一个成员变量, 判断输出的内容 (是 1-26 或是 27-52 或是 A-Z)
- private int flag=1;
- // 定义一个成员变量, 用作计数器
- private int count=0;
- // 定义三个成员变量, 作为 3 种内容的输出初始值
- private int num1=1;
- private int num2=2;
- private char ch='A';
- // 定义一个成员方法, 获得计数器的值
- public int getCount() {
- return count;
- }
- // 输出 1-26
- public synchronized void printNum1() {
- while(flag!=1) {
- try {
- wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.out.print(num1);
- flag=2;
- count++;
- num1+=2;
- notifyAll();
- }
- // 输出 27-52
- public synchronized void printNum2() {
- while(flag!=2) {
- try {
- wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.out.print(num2);
- flag=3;
- count++;
- num2+=2;
- notifyAll();
- }
- // 输出 A-Z
- public synchronized void printChar() {
- while(flag!=3) {
- try {
- wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.out.print(ch);
- flag=1;
- count++;
- ch+=1;
- notifyAll();
- }
- }
- // 用实现 Runnable 接口的方式来实现多线程
- class MyRunnable implements Runnable{
- private PrintNumChar p;
- public MyRunnable(PrintNumChar p) {
- this.p=p;
- }
- public void run() {
- while(p.getCount()<76) {
- if(Thread.currentThread().getName().equals("A")) {
- p.printNum1();
- }
- else if(Thread.currentThread().getName().equals("B")) {
- p.printNum2();
- }
- else if(Thread.currentThread().getName().equals("C")) {
- p.printChar();
- }
- }
- }
- }
2, 仔细审题之后, 再改进为两个线程版的程序:
测试类:
- package print1;
- public class Test
- {
- public static void main(String[] args) {
- PrintNumChar p=new PrintNumChar();
- MyRunnable my=new MyRunnable(p);
- Thread t1=new Thread(my,"A");
- Thread t2=new Thread(my,"B");
- t1.start();
- t2.start();
- }
- }
打印类:
- package print1;
- /**
- * 写两个线程, 一个线程打印 1-52, 另一个线程打印 A-Z, 打印顺序是 12A34B...5152Z.
- */
- public class PrintNumChar
- {
- // 定义一个成员变量, 判断输出的内容 (是 1-52 或是 A-Z)
- private int flag=1;
- // 定义一个成员变量, 用作计数器
- private int count=0;
- // 定义三个成员变量, 作为 3 种内容的输出初始值
- private int num1=1;
- private char ch='A';
- // 定义一个成员方法, 获得计数器的值
- public int getCount() {
- return count;
- }
- // 输出 1-52
- public synchronized void printNum1() {
- while(flag!=1) {
- try {
- wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.out.print(num1*2-1);
- System.out.print(num1*2);
- flag=2;
- count++;
- num1++;
- notifyAll();
- }
- // 输出 A-Z
- public synchronized void printChar() {
- while(flag!=2) {
- try {
- wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.out.print(ch);
- flag=1;
- count++;
- ch+=1;
- notifyAll();
- }
- }
- // 用实现 Runnable 接口的方式来实现多线程
- class MyRunnable implements Runnable{
- private PrintNumChar p;
- public MyRunnable(PrintNumChar p) {
- this.p=p;
- }
- public void run() {
- while(p.getCount()<51) {
- if(Thread.currentThread().getName().equals("A")) {
- p.printNum1();
- }
- else if(Thread.currentThread().getName().equals("B")) {
- p.printChar();
- }
- }
- }
- }
二, 编写一个程序, 启动三个线程, 三个线程的名称分别是 A,B,C.
每个线程将自己的名称在屏幕上打印 5 遍, 打印顺序是 ABCABC...
分析: 结题思路和上面的题一致, 只是输出的内容不一样而已.
测试类:
- class Test{
- public static void main(String[] args) {
- Print print=new Print();
- MyThread my=new MyThread(print);
- Thread t1=new Thread(my,"A");
- Thread t2=new Thread(my,"B");
- Thread t3=new Thread(my,"C");
- t1.start();
- t2.start();
- t3.start();
- }
- }
打印类:
- public class Print
- {
- // 打印哪个字符的标志
- private int flag=1;
- // 打印次数计数器
- private int count=0;
- // 获得打印次数
- public int getCount() {
- return count;
- }
- // 打印 "A" 的方法
- public synchronized void printA() {
- while(flag!=1) {
- try {
- wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.out.print(Thread.currentThread().getName());
- // 打印完成后, 将标识改为 2, 计数器也加 1, 并唤醒其他等待线程
- flag=2;
- count++;
- notifyAll();
- }
- public synchronized void printB() {
- while(flag!=2) {
- try {
- wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.out.print(Thread.currentThread().getName());
- flag=3;
- count++;
- notifyAll();
- }
- public synchronized void printC() {
- while(flag!=3) {
- try {
- wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.out.print(Thread.currentThread().getName());
- flag=1;
- count++;
- notifyAll();
- }
- }
- // 通过实现 Runnable 接口的方式来实现多线程
- class MyThread implements Runnable{
- private Print print;
- public MyThread(Print print) {
- this.print=print;
- }
- public void run() {
- while(print.getCount()<13) {
- if(Thread.currentThread().getName().equals("A")) {
- print.printA();
- }
- else if(Thread.currentThread().getName().equals("B")) {
- print.printB();
- }
- else if(Thread.currentThread().getName().equals("C")) {
- print.printC();
- }
- }
- }
- }
三, 编写程序实现, 子线程循环 3 次, 接着主线程循环 5 次, 接着再子线程循环 3 次, 主线程循环 5 次, 如此反复, 循环 3 次.
测试类:
- public class Test {
- public static void main(String[] args) {
- ThreadFunction f2=new ThreadFunction();
- // 子线程循环 3 次: 用 start() 方法调用 3 次 run() 方法
- new Thread(new Runnable() {
- public void run() {
- for(int i=0;i<3;i++) {
- f2.subFunction();
- }
- }
- }).start();
- // 主线程循环 3 次: 普通的方法调用 3 次
- for(int i=0;i<3;i++) {
- f2.mainFunction();
- }
- }
- }
打印类:
- class ThreadFunction{
- private boolean flag=false;
- public synchronized void mainFunction() {
- while(!flag) {
- try {
- wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- // 主线程输出 5 次
- for(int i=0;i<5;i++) {
- System.out.println("mainFunction"+i);
- }
- notify();
- flag=false;
- }
- public synchronized void subFunction() {
- while(flag) {
- try {
- wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- // 子线程输出 3 次
- for(int i=0;i<3;i++) {
- System.out.println("subFunction"+i);
- }
- notify();
- flag=true;
- }
- }
四, 总结
今天做的所有线程练习, 基本上都是采用的 synchronized 关键字的做法. 在学线程的最初级阶段, 我感觉把这一种做法学透彻就够用了. 拿第三题来说, 不仅用了线程同步的知识, 还涉及到了前面学过的匿名内部类. 但是要想彻底掌握线程的相关知识点, 做这点打印程序的练习还是不够的. 所以后续会多做几道生产者消费者的题来巩固一下.
来源: http://www.bubuko.com/infodetail-3508162.html