一、写两个线程,一个线程打印 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关键字的做法。在学线程的最初级阶段,我感觉把这一种做法学透彻就够用了。拿第三题来说,不仅用了线程同步的知识,还涉及到了前面学过的匿名内部类。但是要想彻底掌握线程的相关知识点,做这点打印程序的练习还是不够的。所以后续会多做几道生产者消费者的题来巩固一下。
原文:https://www.cnblogs.com/yizhinailu/p/12706583.html