CyclicBarrier 支持一个可选的 Runnable
命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。
实现如下:
package andy.thread.test;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author Zhang,Tianyou
* @version 2014年11月9日 下午14:16:01
*/
public class CyclicBarrierTest {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final CyclicBarrier cb = new CyclicBarrier(3);
for (int i = 0; i < 3; i++) {
Runnable runnable = new Runnable() {
public void run() {
try {
Thread.sleep((long) (Math.random() * 10000));
System.out.println("线程"
+ Thread.currentThread().getName()
+ "即将到达集合地点1,当前已有"
+ (cb.getNumberWaiting() + 1)
+ "个已经到达,"
+ (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊"
: "正在等候"));
cb.await();
Thread.sleep((long) (Math.random() * 10000));
System.out.println("线程"
+ Thread.currentThread().getName()
+ "即将到达集合地点2,当前已有"
+ (cb.getNumberWaiting() + 1)
+ "个已经到达,"
+ (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊"
: "正在等候"));
cb.await();
Thread.sleep((long) (Math.random() * 10000));
System.out.println("线程"
+ Thread.currentThread().getName()
+ "即将到达集合地点3,当前已有"
+ (cb.getNumberWaiting() + 1)
+ "个已经到达,"
+ (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊"
: "正在等候"));
cb.await();
} catch (Exception e) {
e.printStackTrace();
}
}
};
service.execute(runnable);
}
service.shutdown();
}
}
线程pool-1-thread-3即将到达集合地点1,当前已有1个已经到达,正在等候
线程pool-1-thread-1即将到达集合地点1,当前已有2个已经到达,正在等候
线程pool-1-thread-2即将到达集合地点1,当前已有3个已经到达,都到齐了,继续走啊
线程pool-1-thread-2即将到达集合地点2,当前已有1个已经到达,正在等候
线程pool-1-thread-1即将到达集合地点2,当前已有2个已经到达,正在等候
线程pool-1-thread-3即将到达集合地点2,当前已有3个已经到达,都到齐了,继续走啊
线程pool-1-thread-1即将到达集合地点3,当前已有1个已经到达,正在等候
线程pool-1-thread-2即将到达集合地点3,当前已有2个已经到达,正在等候
线程pool-1-thread-3即将到达集合地点3,当前已有3个已经到达,都到齐了,继续走啊
二、 Exchanger类
可以在对中对元素进行配对和交换的线程的同步点。每个线程将条目上的某个方法呈现给 exchange
方法,与伙伴线程进行匹配,并且在返回时接收其伙伴的对象。Exchanger 可能被视为 SynchronousQueue
的双向形式。Exchanger 可能在应用程序(比如遗传算法和管道设计)中很有用。
比如两个线程值在某一时刻交换
实现如下:
package andy.thread.test;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author Zhang,Tianyou
* @version 2014年11月9日 下午2:54:26
*/
public class ExchangerTest {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
Exchanger<String> exchanger = new Exchanger<String>();
service.execute(new Runnable() {
public void run() {
try {
String value1 = "value 1";
System.out.println("线程" + Thread.currentThread().getName()
+ "正在把数据" + value1 + "换出去");
Thread.sleep((long) (Math.random() * 10000));
// 等待另一个线程到达此交换点(除非当前线程被中断),然后将给定的对象传送给该线程,并接收该线程的对象。
String value2 = (String) exchanger.exchange(value1);
System.out.println("线程" + Thread.currentThread().getName()
+ "换回的数据为" + value2);
} catch (Exception e) {
}
}
});
service.execute(new Runnable() {
public void run() {
try {
String value2 = "vlaue 2";
System.out.println("线程" + Thread.currentThread().getName()
+ "正在把数据" + value2 + "换出去");
Thread.sleep((long) (Math.random() * 10000));
String value1 = (String) exchanger.exchange(value2);
System.out.println("线程" + Thread.currentThread().getName()
+ "换回的数据为" + value1);
} catch (Exception e) {
}
}
});
}
}
交换了两个线程的值,结果如下:
线程pool-1-thread-1正在把数据value 1换出去
线程pool-1-thread-2正在把数据vlaue 2换出去
线程pool-1-thread-2换回的数据为value 1
线程pool-1-thread-1换回的数据为vlaue 2