1:需求:子線程執行10次,主線程執行100次,再子線程10次,主線程100次,如此的往復50次。
2爲了方便看結果,先把次數改成10次,10次,10次。
3總結:
①互斥:同一塊代碼的原子性操作,不容其它代碼打亂
②同步:不同代碼塊之間,在互斥的基礎上,按照順序執行 ③對於互斥和同步的代碼塊,應該使用業務類來處理,要獨立於線程類,再讓線程類來調用業務類,實現需求。
代碼:
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 < 10; i++) {
business.sub(i);
}
}
}).start();
for (int i = 0; i < 10; i++) {
business.main(i);
}
}
}
/*
* 更面向對象:將線程執行的任務邏輯放到一個業務類裏面,<br>
* 在業務類中控制他們的互斥和同步<br>
* ①使用synchronized進行互斥,說到底就是同一代碼的原子性,不可再分。<br>
* ②使用一個變量bShouldSub進行同步,說到底就是不同代碼的執行順序。<br>
*/
class Business {
boolean bShouldSub = true;
public synchronized void sub(int i) {
//當代碼進來後,線程發現不該自己運行(逆向思維),於是等待,並喚醒其他線程
/*
* 有時候線程是僞喚醒:即其他線程還在執行,這個線程就醒了,也要執行,就會
* 打亂其他線程的執行。這時,要繼續判斷一下這個線程是否滿足執行條件,使用while即可。
*/
while (!bShouldSub) {
try {
this.wait(); //線程等待:即代碼中斷
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//當該自己走,走完後,將bShuouldSub置false,並喚醒其他線程
for (int j = 0; j < 10; j++) {
System.out.println("sub thread sequence of " + j + ",loop of" + i);
}
bShouldSub=false;
this.notify();//由於另一個線程可能進入了wait,需要喚醒
}
public synchronized void main(int i) {
//當代碼進來後,線程發現不該自己運行(逆向思維),於是等待,並喚醒其他線程
while (bShouldSub) {
try {
this.wait(); //線程等待:即代碼中斷
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//當該自己走,走完後,將bShuouldSub置true,並喚醒其他線程
for (int j = 0; j < 10; j++) {
System.out.println("main thread sequence of " + j + ",loop of" + i);
}
bShouldSub=true;
this.notify();//由於另一個線程可能進入了wait,需要喚醒
}
}