類java.util.concurrent.Exchanger提供了一個同步點,在這個同步點,一對線程可以交換數據。每個線程通過exchange()方法的入口提供數據給他的伙伴線程,并接收他的伙伴線程提供的數據,并返回。
當在運行不對稱的活動時很有用,比如當一個線程填充了buffer,另一個線程從buffer中消費數據的時候,這兩個線程可以用Exchanger來交換數據。當兩個線程通過Exchanger交換數據的時候,這個交換對于兩個線程來說是線程安全的。兩個線程都會等到自己的程序運行到Exchanger這個地方時,進行等待。然后再進行數據交換,交換完畢后,各自進行以后的程序流程。
以下這個程序demo要做的事情就是生產者在交換前生產5個"生產者",然后再與消費者交換5個數據,然后再生產5個"交換后生產者",而消費者要在交換前消費5個"消費者",然后再與生產者交換5個數據,然后再消費5個"交換后消費者"。
import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.concurrent.Exchanger;/*** 兩個線程間的數據交換**/ @SuppressWarnings("all") public class ExchangerDemo {private static final Exchanger ex = new Exchanger();class DataProducer implements Runnable {private List list = new ArrayList();public void run() {System.out.println("生產者開始運行");System.out.println("開始生產數據");for (int i = 1; i <= 5; i++) {System.out.println("生產了第" + i + "個數據,耗時1秒");list.add("生產者" + i);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("生產數據結束");System.out.println("開始與消費者交換數據");try {// 將數據準備用于交換,并返回消費者的數據list = (List) ex.exchange(list);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("結束與消費者交換數據");System.out.println("生產者與消費者交換數據后,再生產數據");for (int i = 6; i < 10; i++) {System.out.println("交換后生產了第" + i + "個數據,耗時1秒");list.add("交換后生產者" + i);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("開始遍歷生產者交換后的數據");// 開始遍歷生產者的數據for (Iterator iterator = list.iterator(); iterator.hasNext();) {System.out.println(iterator.next());}}}class DataConsumer implements Runnable {private List list = new ArrayList();public void run() {System.out.println("消費者開始運行");System.out.println("開始消費數據");for (int i = 1; i <= 5; i++) {System.out.println("消費了第" + i + "個數據");// 消費者產生數據,后面交換的時候給生產者list.add("消費者" + i);}System.out.println("消費數據結束");System.out.println("開始與生產者交換數據");try {// 進行數據交換,返回生產者的數據list = (List) ex.exchange(list);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("消費者與生產者交換數據后,再消費數據");for (int i = 6; i < 10; i++) {System.out.println("交換后消費了第" + i + "個數據");list.add("交換后消費者" + i);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("開始遍歷消費者交換后的數據"); for (Iterator iterator = list.iterator(); iterator.hasNext();) {System.out.println(iterator.next());}}}public static void main(String args[]) {ExchangerDemo et = new ExchangerDemo();new Thread(et.new DataProducer()).start();new Thread(et.new DataConsumer()).start();} }
運行結果:
生產者開始運行
開始生產數據
生產了第1個數據,耗時1秒
消費者開始運行
開始消費數據
消費了第1個數據
消費了第2個數據
消費了第3個數據
消費了第4個數據
消費了第5個數據
消費數據結束
開始與生產者交換數據
生產了第2個數據,耗時1秒
生產了第3個數據,耗時1秒
生產了第4個數據,耗時1秒
生產了第5個數據,耗時1秒
生產數據結束
開始與消費者交換數據
結束與消費者交換數據
生產者與消費者交換數據后,再生產數據
交換后生產了第6個數據,耗時1秒
消費者與生產者交換數據后,再消費數據
交換后消費了第6個數據
交換后生產了第7個數據,耗時1秒
交換后消費了第7個數據
交換后消費了第8個數據
交換后生產了第8個數據,耗時1秒
交換后消費了第9個數據
交換后生產了第9個數據,耗時1秒
開始遍歷生產者交換后的數據
消費者1
消費者2
消費者3
消費者4
消費者5
交換后生產者6
交換后生產者7
交換后生產者8
交換后生產者9
開始遍歷消費者交換后的數據
生產者1
生產者2
生產者3
生產者4
生產者5
交換后消費者6
交換后消費者7
交換后消費者8
交換后消費者9
?