如何通过示例使用Java中的Exchanger
大家好,如果您在并發Java應用程序中工作,那么您可能聽說過java.util.concurrent包的Exchanger類。 Java中的Exchanger是Java 1.5中與CountDownLatch , CyclicBarrier和Semaphores一起引入的另一個并發或同步實用程序。 顧名思義, Exchanger允許兩個線程在集合點或集合點見面并交換數據。 的
java.util.Exchanger是一個參數類,它定義并保存要交換的對象的類型。 它有一個重載的方法,稱為
exchange() ,用于在線程之間交換對象。 這是一種阻塞方法,這意味著線程將調用 exchange()方法在交換點等待,直到另一個線程到達。 一旦另一個線程到達,兩個線程都交換對象并從此方法返回。 交換方法的重載版本接受其他 TimeUnit對象,并等待直到超時。
順便說一句,您還可以中斷在交換點等待其他參與者的線程。 與CountDownLatch , CyclicBarrier或Semaphore , Exchanger實用程序只能同步兩個線程,這使其非常適合解決經典的生產者-消費者問題 。
在本Java并發教程中,您將通過使用Exchanger實現生產者-消費者設計模式來學習如何在Java中使用Exchanger。 順便說一句,我假設您熟悉Java編程語法和語義,如果您是Java的完整入門者,那么您可能會很難理解這個示例。
Exchanger類是一個易于理解和使用的簡單同步實用程序。 在最后的兩個并發教程中,我們使用了wait和notify解決了生產者使用者(請參閱此處 ),還使用BlockingQueue實現了生產者-消費者 ,現在該使用Exchanger來實現了。
在此Java并發性教程中, 我們將創建一個生產者和一個使用者線程 ,它們將使用Exchanger實用程序類交換緩沖區。
通常,這是Exchanger的工作方式:
1.首先,創建一個Exchange對象,例如Exchanger<Deque<Long>> stringExchanger = new Exchanger<>() ; 這定義了線程之間將交換什么類型的對象。 在這種情況下,兩個線程將交換包含長值的Deque對象。
2.當線程A準備交換其緩沖區或對象時,它將調用
Exchanger.exchange()方法。 這是一種阻塞方法 , 線程A將被阻塞,直到線程B到來并將其對象傳輸到線程A 為止,否則線程A被中斷或超時。
3.線程B準備就緒時,它還會調用exchange()方法。 現在,線程A和B互相交換對象,并從交換方法返回。
4.交換完成后,線程A具有線程B的對象,反之亦然。
同樣,我想強調Java并發技能的重要性,并敦促每個Java開發人員花一些時間來掌握Java并發類。
帶有Exchanger并發的Java程序
import java.util.ArrayDeque; import java.util.Deque; import java.util.concurrent.Exchanger; ? /** * Exchanger Example in Java. Exchanger allows two Threads to meet at exchange * point and exchange data structure or objects. In this Java program, exchanger * is used to exchange buffer between producer and consumer. ?* @author Javin Paul ?*/ ? public class JavaExchangerTutorail { ???public static void main(String args[]) throws InterruptedException { ??//Creating Exchanger to exchange String object with other thread final Exchanger> exchanger = new Exchanger>(); ??Thread producer = new Thread( "Producer : " ){ ?@Override public void run(){ ?ArrayDeque(); Deque stack = new ArrayDeque(); ?//producer thread insert elments into stack while (stack.isEmpty()) { ?stack.add(System.nanoTime()% 1000 ); //if stack is not empty then exchange it to consumer thread ?try { ?System.out.println(Thread.currentThread().getName() + " ready to exchange : " + stack); <br> // Exchanger return other Thread's object stack = exchanger.exchange(stack); System.out.println(Thread.currentThread().getName() + " got : " + stack); ?} catch (InterruptedException ie) { ie.printStackTrace(); } (InterruptedException ie) { ie.printStackTrace(); } ?} ?} ?}; ???Thread consumer = new Thread( "Consumer : " ){ ?@Override ?public void run(){ ?ArrayDeque(); Deque stack = new ArrayDeque(); ??//consumer thread takes object from stack and prints ?do { //if stack is empty then exchange it to producer for refill try { ?System.out.println(Thread.currentThread().getName() + " ready to exchange : " + stack); stack = exchanger.exchange(stack); System.out.println(Thread.currentThread().getName() + " got : " + stack); stack.remove(); ?} catch (InterruptedException ie) { ie.printStackTrace(); } (InterruptedException ie) { ie.printStackTrace(); } ?} while (stack.isEmpty()) ; ???} ?}; ???producer.start(); <br> //sleeping before starting consumer to give producer time to produce Thread.sleep( 1000 ); consumer.start(); ???} ??? } ??? Output: ? Producer : ready to exchange : [ 247 ] ? Consumer : ready to exchange : [] ? Producer : got : [] ? Consumer : got : [ 247 ] ? Producer : ready to exchange : [ 692 ] ? Consumer : ready to exchange : [] ? Consumer : got : [ 692 ] ? Consumer : ready to exchange : [] ? Producer : got : [] <br>代碼和輸出說明
如果看上面的示例,所有代碼都在main方法內部。 之所以使Exchanger實例成為最終實例,是因為我們要從匿名內部類訪問它們,并且只能從匿名內部類訪問最終局部變量。
后來,我們創建了兩個線程, Producer和Consumer 。 生產者檢查隊列,如果隊列為空,則將當前nano時間的最后三位相加并調用exchange()方法。
現在,直到消費者線程到達交換點,我的意思是直到生產者線程調用exchange()方法,生產者線程才會被阻塞。
使用者到達后,雙方互相交換堆棧并從exchange()方法返回。 此時,生產者有一個空的消費者堆棧,而消費者有一個非空的生產者堆棧,我的意思是,他們有彼此的對象 。
為了理解哪個線程正在交換哪個堆棧,我們在每個線程交換之前和之后打印堆棧的內容。 如果您查看輸出,這是不言自明的。
順便提一下,與線程一樣,不能保證以相同的順序獲得輸出。 在第三次迭代中,您可以看到使用者具有一個已清空的堆棧,甚至可以在安排生產者線程并從交換方法返回之前,準備交換空堆棧。
這就是如何在Java中使用Exchanger的全部內容。 交換器類是一個很好的簡單同步工具,非常適合于協調兩個線程。 應該使用交換器來實現具有一個生產者和一個消費者的生產者-消費者模式。 如果您想了解有關Java并發類的更多信息,建議您檢查以下資源:
進階學習
完整的Java Masterclass Java多線程,并發和性能優化 Java并發實踐–本書 將并發和多線程應用于常見的Java模式
您可能喜歡的其他Java并發文章
- 2020 Java開發人員路線圖 ( 路線圖 )
- Java并發之前發生了什么? ( 回答 )
- 10個Java多線程和并發最佳實踐( 文章 )
- Java中的前50個多線程和并發問題( 問題 )
- 掌握Java并發性的5大書籍( 書籍 )
- 10個面向初學者和中級開發者的免費Java課程( 課程 )
- 如何避免Java死鎖? ( 回答 )
- 了解Java程序中的數據和代碼流( 回答 )
- Java Concurrency in Practice是否在2020年仍然有效( 回答 )
- Java中CyclicBarrier和CountDownLatch之間的區別? ( 回答 )
- 10個技巧,成為2020年的一個更好的Java開發( 提示 )
- 如何使用wait-notify在Java中進行線程間通信? ( 回答 )
- 深入學習Java多線程的前5門課程( 課程 )
感謝您到目前為止閱讀本文。 如果您喜歡此Java并發教程,請與您的朋友和同事分享。 如果您有任何問題或反饋,請留下筆記。
PS –如果您是Java世界的新手,并且想與Concurrency一起學習核心概念,但是想找一些免費的入門課程,那么您也可以在Udemy上查看此免費的Java Multithreading課程 。 這也是學習Java并發性的一門很好的免費課程。
翻譯自: https://www.javacodegeeks.com/2020/05/how-to-use-exchanger-in-java-with-example.html
總結
以上是生活随笔為你收集整理的如何通过示例使用Java中的Exchanger的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 高通:预计上海公司将裁员,但“大规模”“
- 下一篇: 类 OPPO Find X3 Pro 设