/*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 ;
}
}