激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - Java多線程之同步工具類Exchanger

Java多線程之同步工具類Exchanger

2022-03-04 00:38冬日毛毛雨 Java教程

這篇文章主要介紹了Java多線程之同步工具類Exchanger,Exchanger 是一個(gè)用于線程間協(xié)作的工具類,Exchanger用于進(jìn)行線程間的數(shù)據(jù)交換,它提供一個(gè)同步點(diǎn),在這個(gè)同步點(diǎn),兩個(gè)線程可以交換彼此的數(shù)據(jù),下面來看看具體內(nèi)容吧

1 Exchanger 介紹

前面分別介紹了CyclicBarrierCountDownLatchSemaphore,現(xiàn)在介紹并發(fā)工具類中的最后一個(gè)Exchange
Exchanger 是一個(gè)用于線程間協(xié)作的工具類,Exchanger用于進(jìn)行線程間的數(shù)據(jù)交換,它提供一個(gè)同步點(diǎn),在這個(gè)同步點(diǎn),兩個(gè)線程可以交換彼此的數(shù)據(jù)。這兩個(gè)線程通過exchange 方法交換數(shù)據(jù),如果第一個(gè)線程先執(zhí)行exchange 方法,它會(huì)一直等待第二個(gè)線程也執(zhí)行exchange 方法,當(dāng)兩個(gè)線程都到達(dá)同步點(diǎn)時(shí),這兩個(gè)線程就可以交換數(shù)據(jù)。

A synchronization point at which threads can pair and swap elements within pairs. Each thread presents some object on entry to the exchange method, matches with a partner thread, and receives its partner's object on return. An Exchanger may be viewed as a bidirectional form of a SynchronousQueue. Exchangers may be useful in applications such as genetic algorithms and pipeline designs.

在以上的描述中,有幾個(gè)要點(diǎn):

  • 此類提供對(duì)外的操作是同步的;
  • 用于成對(duì)出現(xiàn)的線程之間交換數(shù)據(jù);
  • 可以視作雙向的同步隊(duì)列;
  • 可應(yīng)用于基因算法、流水線設(shè)計(jì)等場(chǎng)景。
  • 接著看api文檔,這個(gè)類提供對(duì)外的接口非常簡(jiǎn)潔,一個(gè)無參構(gòu)造函數(shù),兩個(gè)重載的范型exchange方法:
?
1
2
public V exchange(V x) throws InterruptedException
public V exchange(V x, long timeout, TimeUnit unit) throws InterruptedException, TimeoutException

2 Exchanger 實(shí)例

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class ExchangerTest {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newCachedThreadPool();
        final Exchanger exchanger = new Exchanger();
        executor.execute(new Runnable() {
            String data = "data1";
 
            @Override
            public void run() {
                doExchangeWork(data, exchanger);
            }
        });
 
        executor.execute(new Runnable() {
            String data = "data2";
 
            @Override
            public void run() {
                doExchangeWork(data, exchanger);
            }
        });
        executor.shutdown();
    }
 
    private static void doExchangeWork(String data, Exchanger exchanger) {
        try {
            System.out.println(Thread.currentThread().getName() + "正在把數(shù)據(jù) " + data + " 交換出去");
            Thread.sleep((long) (Math.random() * 1000));
 
            String exchangeData = (String) exchanger.exchange(data);
            System.out.println(Thread.currentThread().getName() + "交換得到數(shù)據(jù)  " + exchangeData);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

pool-1-thread-1正在把數(shù)據(jù) data1 交換出去
pool-1-thread-2正在把數(shù)據(jù) data2 交換出去
pool-1-thread-2交換得到數(shù)據(jù)  data1
pool-1-thread-1交換得到數(shù)據(jù)  data2

當(dāng)線程A調(diào)用Exchange對(duì)象的exchange()方法后,他會(huì)陷入阻塞狀態(tài),直到線程B也調(diào)用了exchange()方法,然后以線程安全的方式交換數(shù)據(jù),之后線程A和B繼續(xù)運(yùn)行。

exchange等待超時(shí)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class ExchangerTest {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newCachedThreadPool();
        final Exchanger exchanger = new Exchanger();
        executor.execute(new Runnable() {
            String data = "data1";
 
            @Override
            public void run() {
                doExchangeWork(data, exchanger);
            }
        });
 
        executor.execute(new Runnable() {
            String data = "data2";
 
            @Override
            public void run() {
                try {
                    Thread.sleep((long) (3000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                doExchangeWork(data, exchanger);
            }
        });
        executor.shutdown();
    }
 
    private static void doExchangeWork(String data, Exchanger exchanger) {
        try {
            System.out.println(Thread.currentThread().getName() + "正在把數(shù)據(jù) " + data + " 交換出去");
 
            //遠(yuǎn)小于3秒拋出異常
            String exchangeData = (String) exchanger.exchange(data,1, TimeUnit.SECONDS);
            System.out.println(Thread.currentThread().getName() + "交換得到數(shù)據(jù)  " + exchangeData);
        } catch ( TimeoutException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

pool-1-thread-1正在把數(shù)據(jù) data1 交換出去
java.util.concurrent.TimeoutException
    at java.util.concurrent.Exchanger.exchange(Exchanger.java:626)
    at ExchangerTest.doExchangeWork(ExchangerTest.java:37)
    at ExchangerTest.access$000(ExchangerTest.java:3)
    at ExchangerTest$1.run(ExchangerTest.java:12)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
pool-1-thread-2正在把數(shù)據(jù) data2 交換出去
java.util.concurrent.TimeoutException
    at java.util.concurrent.Exchanger.exchange(Exchanger.java:626)
    at ExchangerTest.doExchangeWork(ExchangerTest.java:37)
    at ExchangerTest.access$000(ExchangerTest.java:3)
    at ExchangerTest$2.run(ExchangerTest.java:26)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

實(shí)戰(zhàn)場(chǎng)景:

設(shè)計(jì)一個(gè)定時(shí)任務(wù),每日凌晨執(zhí)行。在定時(shí)任務(wù)中啟動(dòng)兩個(gè)線程,一個(gè)線程負(fù)責(zé)對(duì)業(yè)務(wù)明細(xì)表(xxx_info)進(jìn)行查詢統(tǒng)計(jì),把統(tǒng)計(jì)的結(jié)果放置在內(nèi)存緩沖區(qū),另一個(gè)線程負(fù)責(zé)讀取緩沖區(qū)中的統(tǒng)計(jì)結(jié)果并插入到業(yè)務(wù)統(tǒng)計(jì)表(xxx_statistics)中。
親,這樣的場(chǎng)景是不是聽起來很有感覺?沒錯(cuò)!兩個(gè)線程在內(nèi)存中批量交換數(shù)據(jù),這個(gè)事情我們可以使用Exchanger去做!

3 實(shí)現(xiàn)原理

Exchanger(交換者)是一個(gè)用于線程間協(xié)作的工具類。Exchanger用于進(jìn)行線程間的數(shù)據(jù)交換。它提供一個(gè)同步點(diǎn),在這個(gè)同步點(diǎn)兩個(gè)線程可以交換彼此的數(shù)據(jù)。這兩個(gè)線程通過exchange方法交換數(shù)據(jù), 如果第一個(gè)線程先執(zhí)行exchange方法,它會(huì)一直等待第二個(gè)線程也執(zhí)行exchange,當(dāng)兩個(gè)線程都到達(dá)同步點(diǎn)時(shí),這兩個(gè)線程就可以交換數(shù)據(jù),將本線程生產(chǎn)出來的數(shù)據(jù)傳遞給對(duì)方。因此使用Exchanger的重點(diǎn)是成對(duì)的線程使用exchange()方法,當(dāng)有一對(duì)線程達(dá)到了同步點(diǎn),就會(huì)進(jìn)行交換數(shù)據(jù)。因此該工具類的線程對(duì)象是成對(duì)的。
Exchanger類提供了兩個(gè)方法,String exchange(V x):用于交換,啟動(dòng)交換并等待另一個(gè)線程調(diào)用exchangeString exchange(V x,long timeout,TimeUnit unit):用于交換,啟動(dòng)交換并等待另一個(gè)線程調(diào)用exchange,并且設(shè)置最大等待時(shí)間,當(dāng)?shù)却龝r(shí)間超過timeout便停止等待。

到此這篇關(guān)于Java多線程之同步工具類Exchanger的文章就介紹到這了,更多相關(guān)Java多線程 Exchanger內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!

原文鏈接:https://juejin.cn/post/7021034812295102501

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产一级不卡毛片 | 一色屋任你操 | 日韩视频在线视频 | 亚洲午夜不卡 | 久久精品国产久精国产 | 久久久久久久亚洲精品 | 欧美.com | 俄罗斯论理片 | 中文字幕在线观看电影 | 午夜精品在线播放 | 成人一级在线 | 精品久久久久久国产 | 毛片在线看免费 | 国产午夜电影在线观看 | 亚洲欧洲日韩av | 免费看a级片 | 国产精品亚洲欧美一级在线 | 国产精品一区二av18款 | 视频国产一区二区 | 依依成人精品视频 | 久久久久久久亚洲视频 | 九九热在线精品视频 | 草免费视频 | 国产一国产精品一级毛片 | 狠狠久久伊人中文字幕 | 久久成人黄色 | 国产乱淫av | 视频在线91 | 久久久久久久一区二区三区 | 草b视频在线观看 | 亚洲成人福利在线 | 久久久久久久午夜 | 亚洲第一成人久久网站 | 亚洲第九十九页 | av性色全交蜜桃成熟时 | 一区二区三区国产视频 | 青青草免费观看完整版高清 | 欧美爱爱视频网站 | 羞羞视频一区 | 久久成年网 | 久久久久久精 |