2.什麼是執行緒間的通訊 ?怎麼實現執行緒通訊
2.1什麼是執行緒通訊以及實現步驟
執行緒間通訊的模型有兩種:共享記憶體和訊息傳遞
執行緒通訊其實就是 ,實現執行緒的交替工作,並傳遞資訊
執行緒間的通訊具體步驟:(涉及上中下部)
建立資源類,在資源類中船艦屬性和操作方法
在資源類操作方法:判斷、操作、通知
建立多個執行緒,呼叫資源類的操作方法
防止虛擬喚醒問題 (if 判讀,只會判斷一次)
2.2 synchronized案例
操作執行緒的時候,等待執行緒使用wait()
通知另外的執行緒操作用notify()、notifyAll()
假設有兩個執行緒,該執行緒在執行過程中,判斷值(不是該值等待,讓其他執行緒搶),操作值,通知另外一個執行緒的排程
實現兩個執行緒 對num 這個值操作,一個執行緒加1,一個執行緒減1,交替實現多次
//第一步 建立資源類,定義屬性和操作方法 class Share { //初始值 private int num = 0; //+1的方法 public synchronized void incr() throws InterruptedException { //第二步 判斷 幹活 通知 if(number != 0) { //判斷number值是否是0,如果不是0,等待 this.wait(); //在哪裡睡,就在哪裡醒 } //如果number值是0,就+1操作 number++; System.out.println(Thread.currentThread().getName()+" :: "+num); //通知其他執行緒 this.notifyAll(); //注意這裡的通知是隨機的,就是隻能通知全部 } //-1的方法 public synchronized void decr() throws InterruptedException { //判斷 if(number != 1) { this.wait(); } //幹活 number--; System.out.println(Thread.currentThread().getName()+" :: "+number); //通知其他執行緒 this.notifyAll(); } } public class ThreadDemo1 { //第三步 建立多個執行緒,呼叫資源類的操作方法 public static void main(String[] args) { Share share = new Share(); //建立執行緒 new Thread(()->{ for (int i = 1; i <=10; i++) { try { share.incr(); //+1 } catch (InterruptedException e) { e.printStackTrace(); } } },"AA").start(); new Thread(()->{ for (int i = 1; i <=10; i++) { try { share.decr(); //-1 } catch (InterruptedException e) { e.printStackTrace(); } } },"BB").start(); } }
可以看到,這時,程式碼是交替進行的 一個 +1 一個執行緒 -1
但是我們考慮如果同時 ,分別兩個執行緒做加減,那會怎麼樣呢?
虛假喚醒 : wait 是在哪裡睡,在哪裡被喚醒只做了一次判斷 虛假喚醒 放在while if 判斷,只 會判斷一次 所以改為while ;迴圈判斷,就會解決虛假喚醒;從而解決這個錯誤
2.3 Lock案例
使用lock先要建立鎖的物件以及通知的物件
放置在資源類中
private Lock lock= new ReentrantLock(); //建立可重鎖 private Condition condition= lock.newCondition(); //他能操作的物件
上鎖 lock.lock();
解鎖 lock.unlock();
以下都為 condition類:
喚醒所有等待的執行緒signalAll(),帶上類名condition.signalAll();
喚醒一個等待執行緒signal(),帶上類名,condition.signal();
造成當前執行緒在接到訊號或者被中斷之前一直處於等待狀態await(),帶上類名,condition.await();
Lock 實現的程式碼基本是相同的,注意上鎖 和解鎖 是自己手動 做的工作,最終都要在finally 解鎖
如果不解鎖,會影響下面以後的執行緒
class LShare{
//這是共享資源,注意鎖的建立和使用,其他的和上面基本相同
private int num=0;
private Lock lock= new ReentrantLock(); //建立可重鎖
private Condition condition= lock.newCondition();
//建立操作的方法
public void add (){
lock.lock(); //首先 手動上鎖;
try { //判斷,幹活,通知
while (num!=0){
condition.await();
//它使用的是這個物件 呼叫方法 等待
}
num++;
System.out.println( Thread.currentThread().getName()+" 幹活完成 :"+num);
condition.signalAll(); //這個通知方法
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock(); //最終不管出現什麼錯誤,都會解鎖
}
}
這就實現了執行緒間的通訊,,即 他們能夠根據 資訊,完成交替的工作
下面就是學如何 定製通訊?(交替進行執行緒,但是每個執行緒的 工作是改變的)