/*2. 创建2个线程,打印从0到99这100个数字,要求线程交叉顺序打印。
比如
线程1: 0
线程2: 1
线程1: 2
线程2: 3
线程1: 4
线程2: 5
注意,要求使用线程间通信的方式实现,即你打印一个数字,我打印一个数字,一直打印到99*/
package practiceagagin; public class Test { //private static Object OddTask; public static void main(String args[]){ PrintNumber printNum = new PrintNumber(100); EvenTask evenTask = new EvenTask(printNum); OddTask oddTask = new OddTask(printNum); Thread thread1 = new Thread(evenTask); Thread thread2 = new Thread(oddTask); thread1.start(); thread2.start(); } } package practiceagagin; public class PrintNumber { protected int upBound;//定义打印数字的上界 protected int currentNum=0; public PrintNumber(int upBound){ this.upBound = upBound; } public int getNum(){ return currentNum; } } package practiceagagin; //这个类的作用是方便代码重用,减少代码量 //因为无论是打印奇数,还是打印偶数,他们的工作流程可以看作是一样的 //看打印机有没有在使用,有的话阻塞自己 //看打印机有没有在使用,没有的话,看是否是自己可以打印的数;是则打印-打印结束唤醒其它进程;不是则阻塞自己(这里不用去唤醒了,阻塞后又怎么能唤醒别人呢?); //数字奇偶的判断,交给数字类来完成;数字类也一样提高了程序的代码质量 abstract class PrintTask implements Runnable { protected PrintNumber printNum; public PrintTask(PrintNumber printNum) { this.printNum = printNum; } @Override public void run() { while (printNum.currentNum < printNum.upBound) {//还没到达上界持续打印 //打印操作,使用打印机需要上锁,通过原子操作控制同步 synchronized (printNum) {//查看打印机有没有在使用;有的话,其它线程阻塞在外面 //没有,既可以打印 //查看自己是否可以打印 if (isShouldPrint()) { System.out.println(Thread.currentThread().getName()+"打印了"+printNum.getNum()); printNum.currentNum++; printNum.notifyAll(); } else { try { printNum.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } public abstract boolean isShouldPrint(); } package practiceagagin; public class EvenTask extends PrintTask { //子类继承,也要定义下构造方法! public EvenTask(PrintNumber printNum) { super(printNum); } public boolean isShouldPrint(){ return printNum.currentNum%2==0 ; } } package practiceagagin; public class OddTask extends PrintTask { public OddTask(PrintNumber printNum){ super(printNum); } public boolean isShouldPrint(){ return printNum.currentNum%2!=0 ; } }