java.util.concurrent包(7)-Exchanger使用
一個人有零食,另一個人有錢,他們兩個想等價交換,對好口號在某個地方相見,一個人先到了之後,必須等另一個人帶著需要的東西來了之後,才能開始交換。
執行緒pool-1-thread-1正在把資料零食換出去public class ExchangerTest { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final Exchanger<String> exchanger = new Exchanger<String>(); service.execute(new Runnable() { public void run() { try { String data1 = "零食"; System.out.println("執行緒" + Thread.currentThread().getName() + "正在把資料" + data1 + "換出去"); Thread.sleep((long) (Math.random() * 1000)); String data2 = exchanger.exchange(data1); System.out.println("執行緒" + Thread.currentThread().getName() + "換回的資料為" + data2); } catch (Exception e) { } } }); service.execute(new Runnable() { public void run() { try { String data1 = "錢"; System.out.println("執行緒" + Thread.currentThread().getName() + "正在把資料" + data1 + "換出去"); Thread.sleep((long) (Math.random() * 1000)); String data2 = exchanger.exchange(data1); System.out.println("執行緒" + Thread.currentThread().getName() + "換回的資料為" + data2); } catch (Exception e) { } } }); } }
執行緒pool-1-thread-2正在把資料錢換出去
執行緒pool-1-thread-2換回的資料為零食
執行緒pool-1-thread-1換回的資料為錢
示例2
這個類在遇到類似生產者和消費者問題時,是非常有用的。來一個非常經典的併發問題:你有相同的資料buffer,一個或多個數據生產者,和一個或多個數據消費者。只是Exchange類只能同步2個執行緒,所以你只能在你的生產者和消費者問題中只有一個生產者和一個消費者時使用這個類。
Exchanger 類有另外一個版本的exchange方法public class Producer implements Runnable { // 要被相互交換的資料型別。 private List<String> buffer; // 用來同步 producer和consumer private final Exchanger<List<String>> exchanger; public Producer(List<String> buffer, Exchanger<List<String>> exchanger) { this.buffer = buffer; this.exchanger = exchanger; } public void run() { // 實現10次交換 for (int i = 0; i < 10; i++) { buffer.add("第" + i + "次生產者的資料" + i); try { // 呼叫exchange方法來與consumer交換資料 System.out.println("第" + i + "次生產者在等待....."); buffer = exchanger.exchange(buffer); System.out.println("第" + i + "次生產者交換後的資料:" + buffer.get(i)); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class Consumer implements Runnable { // 用來相互交換 private List<String> buffer; // 用來同步 producer和consumer private final Exchanger<List<String>> exchanger; public Consumer(List<String> buffer, Exchanger<List<String>> exchanger) { this.buffer = buffer; this.exchanger = exchanger; } public void run() { // 實現10次交換 for (int i = 0; i < 10; i++) { buffer.add("第" + i + "次消費者的資料" + i); try { // 呼叫exchange方法來與consumer交換資料 System.out.println("第" + i + "次消費者在等待....."); buffer = exchanger.exchange(buffer); System.out.println("第" + i + "次消費者交換後的資料:" + buffer.get(i)); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class Core { public static void main(String[] args) { // 建立2個buffers,分別給producer和consumer使用 List<String> buffer1 = new ArrayList<String>(); List<String> buffer2 = new ArrayList<String>(); // 建立Exchanger物件,用來同步producer和consumer Exchanger<List<String>> exchanger = new Exchanger<List<String>>(); // 建立Producer物件和Consumer物件 Producer producer = new Producer(buffer1, exchanger); Consumer consumer = new Consumer(buffer2, exchanger); // 建立執行緒來執行producer和consumer並開始執行緒 Thread threadProducer = new Thread(producer); Thread threadConsumer = new Thread(consumer); threadProducer.start(); threadConsumer.start(); } }
exchange(V data, long time, TimeUnit unit)
V是宣告引數種類,例子中是List
此執行緒會休眠直到另一個執行緒到達並中斷它,或者特定的時間過去了
TimeUnit類有多種常量,DAYS、HOURS、MICROSECONDS、MILLISECONDS、MINUTES、NANOSECONDS和SECONDS
原帖地址:
http://blog.csdn.net/howlaa/article/details/19853447
http://ifeve.com/thread-synchronization-utilities-8/