深切怀念传智播客张孝祥老师,特将其代表作——Java并发库视频研读两遍,受益颇丰,记以后阅
17.java5的Exchanger同步工具
用于实现两个人之间的数据交换,每个人在完成一定的事务后想与对方交换数据,第一个先拿出数据的人会一直等待第二个人,直到第二个人拿着数据到来时,才能彼此交换数据。
举例:毒品交易 双方并不是同时到达,有先有后,只有都到达了,瞬间交换数据,各自飞
代码演示:
ExecutorService service =Executors.newCachedThreadPool();
final Exchanger exchanger = newExchanger();
毒贩:
service.execute(new Runnable()
{ 毒贩做的事
public void run()
{
String(毒品) data1 = 毒品
SOP(毒贩正在将data1换出去)
Thread.sleep(Random)换的过程
毒贩到位了,拿着毒品等待毒人接头,接头后就能换到钱了
String data2 = (String)exchanger.exchange(data1);
SOP(毒贩换到了钱:data2)
}
});
毒人:
service.execute(new Runnable()
{ 吸毒人做的事
public void run()
{
String(钱) data1 = 钱
SOP(毒人正在将data1换出去)
Thread.sleep(Random)换的过程
吸毒人到位了,拿着钱等待毒贩接头,接头后就能换到毒品了
String data2 =(String)exchanger.exchange(data1);
SOP(毒人换到了毒品:data2)
}
});
java.util.concurrent.Exchanger<V> V -可以交换的对象类型
可以在对中对元素进行配对和交换的线程的同步点。每个线程将条目上的某个方法呈现给exchange方法,与伙伴线程进行匹配,并且在返回时接收其伙伴的对象。Exchanger 可能被视为SynchronousQueue 的双向形式。Exchanger 可能在应用程序(比如遗传算法和管道设计)中很有用。
用法示例:以下是重点介绍的一个类,该类使用Exchanger 在线程间交换缓冲区,因此,在需要时,填充缓冲区的线程获取一个新腾空的缓冲区,并将填满的缓冲区传递给腾空缓冲区的线程。
class FillAndEmpty {
Exchanger<DataBuffer> exchanger = newExchanger<DataBuffer>();
DataBuffer initialEmptyBuffer = ... a made-up type
DataBuffer initialFullBuffer = ...
class FillingLoop implements Runnable {
public void run() {
DataBuffer currentBuffer = initialEmptyBuffer;
try {
while (currentBuffer != null) {
addToBuffer(currentBuffer);
if (currentBuffer.isFull())
currentBuffer = exchanger.exchange(currentBuffer);
}
} catch (InterruptedException ex) { ... handle ... }
}
}
class EmptyingLoop implements Runnable {
public void run() {
DataBuffer currentBuffer = initialFullBuffer;
try {
while (currentBuffer != null) {
takeFromBuffer(currentBuffer);
if (currentBuffer.isEmpty())
currentBuffer = exchanger.exchange(currentBuffer);
}
} catch (InterruptedException ex) { ... handle ...}
}
}
void start() {
new Thread(new FillingLoop()).start();
new Thread(new EmptyingLoop()).start();
}
}
构造方法摘要 |
|
Exchanger() 创建一个新的 Exchanger。 |
|
方法摘要 |
|
V |
exchange(V x) 等待另一个线程到达此交换点(除非当前线程被中断),然后将给定的对象传送给该线程,并接收该线程的对象。 |
V |
exchange(V x, long timeout,TimeUnit unit) 等待另一个线程到达此交换点(除非当前线程被中断,或者超出了指定的等待时间),然后将给定的对象传送给该线程,同时接收该线程的对象。 |
public class ExchangerTest {
publicstatic void main(String[] args) {
ExecutorServiceservice = Executors.newCachedThreadPool();
finalExchanger exchanger = new Exchanger();
service.execute(newRunnable(){
publicvoid run() {
try{
Stringdata1 = "zxx";
System.out.println("线程" +Thread.currentThread().getName() +
"正在把数据" + data1 +"换出去");
Thread.sleep((long)(Math.random()*10000));
Stringdata2 = (String)exchanger.exchange(data1);
System.out.println("线程" + Thread.currentThread().getName()+
"换回的数据为" + data2);
}catch(Exceptione){
}
}
});
service.execute(newRunnable(){
publicvoid run() {
try{
Stringdata1 = "lhm";
System.out.println("线程" +Thread.currentThread().getName() +
"正在把数据" + data1 +"换出去");
Thread.sleep((long)(Math.random()*10000));
Stringdata2 = (String)exchanger.exchange(data1);
System.out.println("线程" +Thread.currentThread().getName() +
"换回的数据为" + data2);
}catch(Exceptione){
}
}
});
}
}
public class ExchangerTest { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final Exchanger exchanger = new Exchanger(); service.execute(new Runnable(){ public void run() { try { String data1 = "zxx"; System.out.println("线程" + Thread.currentThread().getName() + "正在把数据" + data1 +"换出去"); Thread.sleep((long)(Math.random()*10000)); String data2 = (String)exchanger.exchange(data1); System.out.println("线程" + Thread.currentThread().getName() + "换回的数据为" + data2); }catch(Exception e){ } } }); service.execute(new Runnable(){ public void run() { try { String data1 = "lhm"; System.out.println("线程" + Thread.currentThread().getName() + "正在把数据" + data1 +"换出去"); Thread.sleep((long)(Math.random()*10000)); String data2 = (String)exchanger.exchange(data1); System.out.println("线程" + Thread.currentThread().getName() + "换回的数据为" + data2); }catch(Exception e){ } } }); } }