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

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
				}
			}
			
		});
	}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值