1. 程式人生 > 其它 >2.什麼是執行緒間的通訊 ?怎麼實現執行緒通訊

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(); //最終不管出現什麼錯誤,都會解鎖
        }
    }

這就實現了執行緒間的通訊,,即 他們能夠根據 資訊,完成交替的工作

下面就是學如何 定製通訊?(交替進行執行緒,但是每個執行緒的 工作是改變的)