Exchanger的工作原理及例項
1.實現原理
Exchanger(交換者)是一個用於執行緒間協作的工具類。Exchanger用於進行執行緒間的資料交換。它提供一個同步點,在這個同步點兩個執行緒可以交換彼此的資料。這兩個執行緒通過exchange方法交換資料, 如果第一個執行緒先執行exchange方法,它會一直等待第二個執行緒也執行exchange,當兩個執行緒都到達同步點時,這兩個執行緒就可以交換資料,將本執行緒生產出來的資料傳遞給對方。因此使用Exchanger的重點是成對的執行緒使用exchange()方法,當有一對執行緒達到了同步點,就會進行交換資料。因此該工具類的執行緒物件是成對的。
Exchanger類提供了兩個方法,String exchange(V x):用於交換,啟動交換並等待另一個執行緒呼叫exchange;String exchange(V x,long timeout,TimeUnit unit):用於交換,啟動交換並等待另一個執行緒呼叫exchange,並且設定最大等待時間,當等待時間超過timeout便停止等待。
2.例項講解
通過以上的原理,可以知道使用Exchanger類的核心便是exchange()方法的使用,接下來通過一個例子來使的該工具類的用途更加清晰。該例子主要講解的是前段時間NBA交易截止日的交易。
package concurrent;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.*;
public class ExchangerDemo {
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
final Exchanger exchanger = new Exchanger();
executor.execute(new Runnable() {
String data1 = "克拉克森,小拉里南斯";
@Override
public void run() {
nbaTrade(data1, exchanger);
}
});
executor.execute(new Runnable() {
String data1 = "格里芬";
@Override
public void run() {
nbaTrade(data1, exchanger);
}
});
executor.execute(new Runnable() {
String data1 = "哈里斯";
@Override
public void run() {
nbaTrade(data1, exchanger);
}
});
executor.execute(new Runnable() {
String data1 = "以賽亞托馬斯,弗萊";
@Override
public void run() {
nbaTrade(data1, exchanger);
}
});
executor.shutdown();
}
private static void nbaTrade(String data1, Exchanger exchanger) {
try {
System.out.println(Thread.currentThread().getName() + "在交易截止之前把 " + data1 + " 交易出去");
Thread.sleep((long) (Math.random() * 1000));
String data2 = (String) exchanger.exchange(data1);
System.out.println(Thread.currentThread().getName() + "交易得到" + data2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
執行程式,得到如下結果:
pool-1-thread-1在交易截止之前把 克拉克森,小拉里南斯 交易出去
pool-1-thread-2在交易截止之前把 格里芬 交易出去
pool-1-thread-3在交易截止之前把 哈里斯 交易出去
pool-1-thread-4在交易截止之前把 以賽亞托馬斯,弗萊 交易出去
pool-1-thread-2交易得到哈里斯
pool-1-thread-3交易得到格里芬
pool-1-thread-4交易得到克拉克森,小拉里南斯
pool-1-thread-1交易得到以賽亞托馬斯,弗萊
以上例子可以看出兩個都呼叫exchange()方法的執行緒會進行交換資料。接下來假設執行緒數目只有奇數個,觀察情況:
如以下程式碼,將第四個執行緒註釋掉。
package concurrent;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.*;
public class ExchangerDemo {
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
final Exchanger exchanger = new Exchanger();
executor.execute(new Runnable() {
String data1 = "克拉克森,小拉里南斯";
@Override
public void run() {
nbaTrade(data1, exchanger);
}
});
executor.execute(new Runnable() {
String data1 = "格里芬";
@Override
public void run() {
nbaTrade(data1, exchanger);
}
});
executor.execute(new Runnable() {
String data1 = "哈里斯";
@Override
public void run() {
nbaTrade(data1, exchanger);
}
});
// executor.execute(new Runnable() {
// String data1 = "以賽亞托馬斯,弗萊";
//
// @Override
// public void run() {
// nbaTrade(data1, exchanger);
// }
// });
executor.shutdown();
}
private static void nbaTrade(String data1, Exchanger exchanger) {
try {
System.out.println(Thread.currentThread().getName() + "在交易截止之前把 " + data1 + " 交易出去");
Thread.sleep((long) (Math.random() * 1000));
String data2 = (String) exchanger.exchange(data1);
System.out.println(Thread.currentThread().getName() + "交易得到" + data2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
執行程式,得到如下結果:
pool-1-thread-1在交易截止之前把 克拉克森,小拉里南斯 交易出去
pool-1-thread-2在交易截止之前把 格里芬 交易出去
pool-1-thread-3在交易截止之前把 哈里斯 交易出去
pool-1-thread-3交易得到格里芬
pool-1-thread-2交易得到哈里斯
由結果可知,執行緒2和執行緒3進行了交換資料,而執行緒1一直等待與它交換資料的執行緒呼叫exchange,但是隻有3個執行緒,所以會一直等待。
因此,當兩個執行緒之間出現資料交換的情況,可以使用Exchanger工具類實現資料交換。注意exchange方法的含義,以及觸發資料交換的條件。
相關文章
- NIO原理及例項
- JVM 垃圾回收器工作原理及使用例項介紹JVM
- pr劫持的原理及操作例項、pr劫持的原理
- SpringCloud——Feign例項及原理SpringGCCloud
- Java 下 SSL 通訊原理及例項Java
- 網路測速一原理及例項
- CGroup 介紹、應用例項及原理描述
- AOP的原理和例項
- 一圖看懂區塊鏈的工作原理、技術及用例區塊鏈
- YUM工作原理及使用
- 詳解 AWS 的突發效能例項:CPU 和頻寬突發的工作原理
- JavaScript 中 this 的工作原理以及注意事項JavaScript
- JavaScript中this的工作原理以及注意事項JavaScript
- ppium簡介及工作原理
- ZIP壓縮演算法原理分析及解壓例項程式碼演算法
- Python物件導向多型實現原理及程式碼例項Python物件多型
- ActiveMQ 入門及例項MQ
- 伺服器重置例項後的部署工作伺服器
- 例項詳解貝葉斯推理的原理
- 效能測試準備工作例項
- Thanos工作原理及元件簡介元件
- Java ArrayDeque工作原理及實現Java
- Java HashMap工作原理及實現JavaHashMap
- TRIZ 機械振動原理 例項
- 大神教你C++寫時複製實現原理及例項解析C++
- Spring WebFlux 的設計及工作原理剖析SpringWebUX
- SSL解除安裝的工作原理及好處
- Vue例項及生命週期Vue
- AWK簡介及使用例項
- Jquery入門及例項一jQuery
- 使用LVS實現負載均衡的原理及安裝配置例項詳解負載
- springmvc工作原理及原始碼分析SpringMVC原始碼
- CSS動畫學習指南:原理與例項CSS動畫
- Python中的if、while、for 語法及例項PythonWhile
- JavaScript中常用的事件程式碼及例項JavaScript事件
- JSTL的標籤及使用,包含例項JS
- rman catalog的配置及詳解例項
- ActiveMQ的使用及整合spring的使用例項MQSpring