Java Exchanger 必知必會

問:你知道 Java 的 Exchanger 嗎?簡單說說其特點及應用場景?

答:Exchanger 是 JDK 1.5 開始提供的一個用于兩個工作線程之間交換數(shù)據(jù)的封裝工具類,簡單說就是一個線程在完成一定的事務后想與另一個線程交換數(shù)據(jù),則第一個先拿出數(shù)據(jù)的線程會一直等待第二個線程,直到第二個線程拿著數(shù)據(jù)到來時才能彼此交換對應數(shù)據(jù)。其定義為 Exchanger<V> 泛型類型,其中 V 表示可交換的數(shù)據(jù)類型,對外提供的接口很簡單,具體如下:

  • Exchanger():無參構造方法。

  • V exchange(V v):等待另一個線程到達此交換點(除非當前線程被中斷),然后將給定的對象傳送給該線程,并接收該線程的對象。

  • V exchange(V v, long timeout, TimeUnit unit):等待另一個線程到達此交換點(除非當前線程被中斷或超出了指定的等待時間),然后將給定的對象傳送給該線程,并接收該線程的對象。

可以看出,當一個線程到達 exchange 調用點時,如果其他線程此前已經調用了此方法,則其他線程會被調度喚醒并與之進行對象交換,然后各自返回;如果其他線程還沒到達交換點,則當前線程會被掛起,直至其他線程到達才會完成交換并正常返回,或者當前線程被中斷或超時返回。

public class Test {
    static class Producer extends Thread {
        private Exchanger<Integer> exchanger;
        private static int data = 0;
        Producer(String name, Exchanger<Integer> exchanger) {
            super("Producer-" + name);
            this.exchanger = exchanger;
        }

        @Override
        public void run() {
            for (int i=1; i<5; i++) {
                try {
                    TimeUnit.SECONDS.sleep(1);
                    data = i;
                    System.out.println(getName()+" 交換前:" + data);
                    data = exchanger.exchange(data);
                    System.out.println(getName()+" 交換后:" + data);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    static class Consumer extends Thread {
        private Exchanger<Integer> exchanger;
        private static int data = 0;
        Consumer(String name, Exchanger<Integer> exchanger) {
            super("Consumer-" + name);
            this.exchanger = exchanger;
        }

        @Override
        public void run() {
            while (true) {
                data = 0;
                System.out.println(getName()+" 交換前:" + data);
                try {
                    TimeUnit.SECONDS.sleep(1);
                    data = exchanger.exchange(data);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(getName()+" 交換后:" + data);
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Exchanger<Integer> exchanger = new Exchanger<Integer>();
        new Producer("", exchanger).start();
        new Consumer("", exchanger).start();
        TimeUnit.SECONDS.sleep(7);
        System.exit(-1);
    }
}

可以看到,其結果可能如下:

Consumer- 交換前:0
Producer- 交換前:1
Consumer- 交換后:1
Consumer- 交換前:0
Producer- 交換后:0
Producer- 交換前:2
Producer- 交換后:0
Consumer- 交換后:2
Consumer- 交換前:0
Producer- 交換前:3
Producer- 交換后:0
Consumer- 交換后:3
Consumer- 交換前:0
Producer- 交換前:4
Producer- 交換后:0
Consumer- 交換后:4
Consumer- 交換前:0

可以看到,如上就是一種典型的使用場景,簡單理解這東西就是一個并發(fā)協(xié)作的工具類而已。

本文參考自 Java/Android Exchanger 必知必會實戰(zhàn)題分析

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容