您的位置:首页 > 编程语言 > Java开发

Java线程知识__其他几种线程同步的工具类的使用(CyclicBarrier,CountDownLatch,Exchanger)

2014-07-22 20:48 876 查看
1,CyclicBarrier类,表示指定数量的线程都在等待吗,只有到齐了才出发进行下面的步骤。

就相当于我们一个班出去春游,规定在图书馆集合,有的同学先到,有的后到,但是先到的

不能先走只有等到全部来齐了,才能上车出发。

示例:模拟同学们出去春游,只有人都到齐了才能进入下一个景点。

import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/*
* 创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,
* 但它不会在启动 barrier 时执行预定义的操作。
*/
public class CyclicBarrierTest {

public static void main(String[] args) {
ExecutorService pools = Executors.newCachedThreadPool();
final CyclicBarrier cb = new CyclicBarrier(3);
for(int i=0;i<3;i++) {
Runnable r = new Runnable() {

@Override
public void run() {
try {
Thread.sleep((long) (Math.random()*10000));
System.out.println("线程" + Thread.currentThread().getName() + "到达集合点1," +
"当前已有:" + (cb.getNumberWaiting() + 1) + "个线程在等待");
cb.await();

Thread.sleep((long) (Math.random()*10000));
System.out.println("线程" + Thread.currentThread().getName() + "到达集合点2," +
"当前已有:" + (cb.getNumberWaiting() + 1) + "个线程在等待");
cb.await();

Thread.sleep((long) (Math.random()*10000));
System.out.println("线程" + Thread.currentThread().getName() + "到达集合点3," +
"当前已有:" + (cb.getNumberWaiting() + 1) + "个线程在等待");
cb.await();

Thread.sleep((long) (Math.random()*10000));
System.out.println("线程" + Thread.currentThread().getName() + "到达集合点4," +
"当前已有:" + (cb.getNumberWaiting() + 1) + "个线程在等待");
cb.await();
} catch (Exception e) {
e.printStackTrace();
}
}
};
pools.execute(r);
}
}
}


2,CountDownLatch类,该类就像是一个倒计时计数器。调用它的countDown()方法将计数器减一,当计数器到达0时,则所有

等待或者单个等待者开始执行。例如要实现一个人(也可以是多个人)等待其他所有人来通知他。可以实现一个人通知多个人

的效果,也可以实现多个人通知一个人的效果。类似裁判一声令下,等待的运动员都开始向前跑。或者当所有运动员到达终

点时,裁判才开始公布结果。

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/*
* 模拟运动员赛跑的过程,运动员等待裁判发命令,当裁判发命令后运动员起跑,只有当所有运动员到达终点后,裁判才能公布
* 结果。
*/
public class CountDownLatchTest {

public static void main(String[] args) {
ExecutorService pool = Executors.newCachedThreadPool();
//裁判计时器对象
final CountDownLatch cdOrder = new CountDownLatch(1);
//创建运动员达到获取结果计时器对象
final CountDownLatch cdAnswer = new CountDownLatch(3);
for(int i=0;i<3;i++) {
Runnable command = new Runnable() {

@Override
public void run() {
try {
System.out.println("线程" + Thread.currentThread().getName() + "正在准备接受命令");
cdOrder.await();
System.out.println("线程" + Thread.currentThread().getName() + "已经接受命令");
Thread.sleep((long) (Math.random()*10000));
System.out.println("线程" + Thread.currentThread().getName() + "等待比赛结果");
cdAnswer.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
};
pool.execute(command);
}

//裁判在主线程中等待另外一个计数器为零
try {
Thread.sleep((long) (Math.random()*10000));
System.out.println("线程" + Thread.currentThread().getName() + "即将发出命令");
cdOrder.countDown();
System.out.println("线程" + Thread.currentThread().getName() + "已经发出命令,等待所有用户达到,公布结果");
cdAnswer.await();
System.out.println("所有用户已经到达,线程" + Thread.currentThread().getName() + "已经公布结果");
} catch (Exception e) {
e.printStackTrace();
}
}

}


3,Exchangeer工具类。(可以在对中对元素进行配对和交换的线程的同步点.)

该类实现两个线程彼此交换数据的过程,当一个线程先打达时,另一个没有到达,那么这个线程会等待

另一个的到来,知道另一个到来了,彼此开始交换数据,交换完后两线程结束,否则其中一个将一直处于

阻塞,等待另一个的到来。

示例:模拟两个人交换数据的过程。

import java.util.Random;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/*
* 两个线程彼此交换数据,只有当两个都到达后才交换数据,线程结束。
*/
public class ExchangerTest {

public static void main(String[] args) {
ExecutorService pool = Executors.newCachedThreadPool();
//创建交换器对象
final Exchanger<String> exchanger = new Exchanger<>();
//向线程池添加两个任务
pool.execute(new Runnable() {

@Override
public void run() {
try {
String data1 = "第一个人的数据";
System.out.println("第一个人正在把" + data1 + "交换出去" );
Thread.sleep(new Random().nextInt(1000));
String data2 = exchanger.exchange(data1);
System.out.println("第一个人换回的数据为:" + data2);
} catch (Exception e) {
// TODO: handle exception
}
}
});

pool.execute(new Runnable() {

@Override
public void run() {
try {
String data1 = "第二个人的数据";
System.out.println("第二个人正在把" + data1 + "交换出去" );
Thread.sleep(new Random().nextInt(1000));
String data2 = exchanger.exchange(data1);
System.out.println("第二个人换回的数据为:" + data2);
} catch (Exception e) {
// TODO: handle exception
}
}

});
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐