问题:多线程交叉打印
典型的生产者消费者模型
初步代码:
class T implements Runnable{
Object o = new Object();
boolean flag = false;
@Override
public void run() {
String s = Thread.currentThread().getName();
if (s.equals("A")) {
while(true){ // 保障线程一直走
System.out.println("1");
synchronized (o){
while(flag){ // 用while(条件)来确保notifyAll即使抢到优先权了不满足条件也给我等待。
System.out.println("11");
try{
o.wait();
}catch (Exception e){
e.printStackTrace();
}
}
System.out.println("thread-a");
flag = true;
o.notifyAll(); // 当某个线程调用notifyAll方法后,虽然其他线程被唤醒了,但是该线程依然持有着对象锁,
// 必须等该同步代码块执行完(右大括号结束)后才算正式释放了锁对象,另外线程才有机会执行
}
}
} else {
while(true){
System.out.println("2");
synchronized (o){
while(!flag){
System.out.println("22");
try{
o.wait();
}catch (Exception e){
e.printStackTrace();
}
}
System.out.println("thread-b");
flag = false;
o.notifyAll();
}
}
}
}
// wait 是对象的锁,释放了锁对象,用notify/notifyAll唤醒,通常用while(!condition){this.wait();}限制不该唤醒的线程(notify只是随机唤醒);
// sleep 是线程的休眠 不会释放锁对象,因为如果别人在休眠状态拿了锁,那就没意义了。
public static void main(String[] args) {
T t = new T();
Thread t1 = new Thread(t, "A");
Thread t2 = new Thread(t, "B");
t1.start();
t2.start();
}
}
以下是某次结果:
1 //a线程首先开启
thread-a //获取锁对象,不满足while条件,打印
1 //notifyAll没用到;A线程继续循环打印
11 //满足while条件,打印后A等待,释放锁对象
2 //B线程终于启动了
thread-b //拿到锁对象,不满足while,打印
2 //打印
thread-a //notifyAll唤醒A后,与B争锁,A赢,不满足while,打印(及时B赢不满足条件还得等待)
1 //打印
thread-b //B争取了锁,不满足while条件,打印
2
thread-a
1
11
thread-b
2
thread-a
1
thread-b
事实上这段代码notifyAll换成notify也没问题,参加博客Java中notify和notifyAll的区别 - 何时以及如何使用
sleep()和wait()的区别及wait方法的一点注意事项
参考资料
参考资料
接下来是写法升级,未完待续。。。