java多线程之传统线程同步通信技术

时间:2022-01-27 18:29:17
wait和notify实例

子线程循环10次,主线程循环100次。接着子线程循环10次,主线程循环100次。如此循环50次。摘自张孝祥老师线程视频源码。

package javaplay.thread.test;

public class TraditionalThreadCommunication {
public static void main(String[] args) {
final Business business = new Business();
new Thread(new Runnable() {

@Override
public void run() {
for (int i = 0; i < 5; i++) {
business.sub(i);
}

}

}).start();

for (int i = 0; i < 5; i++) {
business.main(i);// 此处不能是sub 否则死锁
}

}
}

// 经验:要用到共同数据(包括同步锁)或共同算法的若干个方法应该归在同一个类身上,
// 这种设计下好体现了高内聚和程序的健壮性
// 锁是上在代表要操作的资源类的内部方法中(就是下面),而不是线程代码中(就是上面)!!!
// 好处是这个类交给任何一个方法去访问,它天然就同步了
class Business {
private boolean bShouldSub = true;//volatile???

// doc:
// synchronized (obj) {
// while (<condition does not hold>)
// obj.wait();
// ... // Perform action appropriate to condition
// }
// .wait必须放在synchronized里面,否则报异常 同步监视器也必须使用同一个
public synchronized void sub(int i) {
// 此处用while效果一样,但程序更健壮,因为可避免spurious wakeup, 即别人没叫就醒了(doc)
if (!bShouldSub) {
try {
this.wait();// 进来sub方法时用得就是this作为同步监视器对象 详见doc
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int j = 0; j < 1; j++) {
System.out.println("sub thread sequence of " + j + " ,loop of " + i);
}
bShouldSub = false;
this.notify();// 详见doc
}

public synchronized void main(int i) {
if (bShouldSub) {// 此处用while效果一样,但程序更健壮
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int j = 0; j < 2; j++) {
System.out.println("main thread sequence of " + j + " ,loop of " + i);
}
bShouldSub = true;
this.notify();
}
}