傳統執行緒同步通訊synchronized
阿新 • • 發佈:2019-01-29
1.典型的生產者消費者問題
先生產再消費,A生產完後 通知B消費 B消費完後通知A 再生產 依次往復。
package com.yanghs.test.pro; /** * @author yanghs * @Description:溝通資源 * @date 2018/3/30 23:49 */ public class Movie { private String pic; /*訊號燈 true生產者生產 false消費者消費*/ private boolean flag = true; public synchronized void play(String pic) throws InterruptedException { if(!flag){ wait(); } this.pic = pic; /*生產完畢 更改訊號燈 為消費者*/ System.out.println("生產完畢"); this.flag = false; this.notify(); } public synchronized void watch() throws InterruptedException { if(flag){ wait(); } System.out.println(pic); System.out.println("消費完畢"); /*t通知生產者*/ this.notify(); this.flag = true; } }
關鍵點 把生產者和消費者抽象為一個類裡面 便於加鎖和通訊 上面是抽象好的一個類
生產者
package com.yanghs.test.pro; /** * @author yanghs * @Description:生產者 * @date 2018/3/30 23:52 */ public class Player implements Runnable { private Movie m; public Player(Movie m) { this.m = m; } @Override public void run() { for(int i=0; i<=20;i++){ try { m.play("aaaaaaaaaa"); } catch (InterruptedException e) { e.printStackTrace(); } } } }
消費者
package com.yanghs.test.pro; /** * @author yanghs * @Description:消費者 * @date 2018/3/30 23:52 */ public class Watcher implements Runnable { private Movie m; public Watcher(Movie m) { this.m = m; } @Override public void run() { for (int i=0; i<=20;i++){ try { m.watch(); } catch (InterruptedException e) { e.printStackTrace(); } } } }
呼叫者
package com.yanghs.test.pro;
/**
* @author yanghs
* @Description:
* @date 2018/3/30 23:59
*/
public class App {
public static void main(String[] args) {
Movie m = new Movie();
Player p = new Player(m);
Watcher w = new Watcher(m);
new Thread(p).start();
new Thread(w).start();
}
}
2.一個面試題
有主執行緒和子執行緒,要求子執行緒先執行5次 後 主執行緒執行 5次 依次往復5次
分析:子執行緒主執行緒是有執行順序的 執行順序可以通過 join 和 synchronized wait notify實現 但是這裡又要求 這個動作要迴圈5次,就是 a>b>a>b... 顯然join不符合。所以應該向wait這邊靠。
1)子執行緒和主執行緒需要相互通知執行 所以先抽象出邏輯程式碼 ab的通訊,synchronized加在方法上 表示鎖定呼叫這個方法的物件 下面的方法就表示鎖定 Business例項化的物件
物件鎖是在一個類的物件上加的的鎖,只有一把,不管有幾個方法進行了同步。
這些同步方法都共有一把鎖,只要一個執行緒獲得了這個物件鎖,其他的執行緒就不能訪問該物件的任何一個同步方法。
class Business{
volatile boolean flag = true;//子執行緒執行 true
public synchronized void sub(){
if(!flag){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int i=0;i<=3;i++){
System.out.println("子執行緒"+i);
}
flag = false;
notify();
}
public synchronized void main(){
if(flag){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int i=0;i<=3;i++){
System.out.println("主執行緒"+i);
}
flag = true;
notify();
}
}
2)呼叫
public class TraSynchronized {
public static void main(String[] args) {
/*建一個業務*/
final Business b = new Business();
/*新建一個子執行緒 並且開啟執行 業務中的sub()*/
new Thread(new Runnable() {
@Override
public void run() {
for(int i =0 ;i<=5;i++){
b.sub();
}
}
}).start();
/*主執行緒執行 main()*/
for(int i =0 ;i<=5;i++){
b.main();
}
}
}
實現效果