【併發】Java中線程的通信方式

目錄

Java中線程通信方式

1. 同步

2. Wait / notify機制

3. 利用volatile

4. 利用AtomicInteger

5. 管道通信

參考


Java中線程通信方式

1. 同步

這裏的同步是指多個線程通過synchronized關鍵字這種方式來實現線程間的通信,簡單說就是,兩個線程,一個線程執行完了,另一個才能執行。

public class MyObject {
​
    synchronized public void methodA() {
        //do something....
    }
​
    synchronized public void methodB() {
        //do some other thing
    }
}
​
public class ThreadA extends Thread {
​
    private MyObject object;
//省略構造方法
    @Override
    public void run() {
        object.methodA();
    }
}
​
public class ThreadB extends Thread {
​
    private MyObject object;
//省略構造方法
    @Override
    public void run() {
        object.methodB();
    }
}
​
public class Run {
    public static void main(String[] args) {
        MyObject object = new MyObject();
​
        //線程A與線程B 持有的是同一個對象:object
        ThreadA a = new ThreadA(object);
        ThreadB b = new ThreadB(object);
        a.start();
        b.start();
    }
}

線程A和線程B持有同一個MyObject類的對象object,儘管這兩個需要調用不同的方法,但是他們是同步執行的,線程B需要等待線程A執行完methodA()方法後,它才能執行methodB()方法。這樣線程A和線程B就實現了通信。

這種方式本質上就是“共享內存”式的通信。多個線程需要訪問同一個變量,誰拿到鎖,誰就可以執行

2. Wait / notify機制

//共享資源對象
public class Can {
    private String type;
    private String date;
    // 表示檢查當前共享資源狀態是否爲空
    private boolean isEmpty = true;
 
    /**
     * 生產者向共享資源中存儲數據
     * 
     * @param type
     *            存儲的罐頭類型
     * @param date
     *            存儲罐頭的生產日期批次
     */
    synchronized public void push(String type, String date) {
        try {
            while (!isEmpty) {//當前共享資源狀態不空,等待消費者來消費
                //使用同步鎖對象調用,表示當前線程釋放同步鎖,進入等待池(休眠)
                //只能等待被其他線程喚醒
                this.wait();
            }
            //-----生產開始-----
            this.type = type;
            Thread.sleep(10);
            this.date = date;
            //-----生產結束-----
            //修改共享資源狀態不爲空
            isEmpty=false;
            //喚醒一個消費者
            this.notifyAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
 
    }
 
    /**
     * 消費者從共享資源中取出數據並打印
     */
    synchronized public void popup() {
        try {
            while(isEmpty){
                //當共享資源狀態爲空,釋放同步鎖,進入等待吃(休眠)
                //等待生產者生產,然後被喚醒
                wait();
            }
            Thread.sleep(10);
            //-----消費開始-----
            System.out.println(this.type + "--->" + this.date);
            //-----消費結束-----
            //修改共享資源狀態爲空
            isEmpty=true;
            //喚醒一個生產者生產
            this.notifyAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
    }
}
​
public class Test {
    public static void main(String[] args) {
        Can can = new Can();
        
        new Thread(new Producer(can)).start();
        new Thread(new Consumer(can)).start();
    }
}
​

可以看到兩個線程生產者和消費者,剛開始沒有罐頭,消費者處於等待狀態,生產者就開始生產罐頭,此時有罐頭了,喚醒消費者,自己進入阻塞狀態,消費者消費空了又把生產者喚醒,一直循環這個過程。

上面兩種通信方式,都屬於共享內存的通信方式,都有一個共享變量,通過Sychronized同步鎖,wait和notify來通知。

3. 利用volatile

volatile修飾的變量值直接存在主內存裏面,子線程對該變量的讀寫直接寫住內存,而不是像其它變量一樣在local thread裏面產生一份copy。volatile能保證所修飾的變量對於多個線程可見性,即只要被修改,其它線程讀到的一定是最新的值。

4. 利用AtomicInteger

和volatile類似

5. 管道通信

Java中有各種各樣的輸入、輸出流(Stream),其中管道流(pipeStream)是一種特殊的流,用於在不同線程間直接傳送數據。Java中的Stream是單向的,所以在兩個線程中分別建了一個PipedInputStream、PipedOutputStream。

參考

https://blog.csdn.net/wlddhj/article/details/83793709

https://www.cnblogs.com/lgyxrk/p/10404839.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章