1,CyclicBarrier

屏障:当线程Ta先执行到了await方法时候,等待;然后Tb又执行到了await方法,继续等待,直到最后一个线程执行到了他自己的await方法之后,图中的三个线程才会继续一块走下去,当传入barrierAction时,所有线程执行完await方法后,会执行barrierAction进行汇总,汇总结束后执行await方法的线程才会继续运行

屏障可以多次使用,await可以反复调用

CyclicBarrier构造方法传入的数字必须和执行任务的线程数量一致

 

与countDownLatch的区别:

  1,CyclicBarrier计数器可以多次使用,同时计数器可以使用reset()方法重置,countDownLatch只能调用一次

  2,CyclicBarrier工作线程本身之间相互协调,countDownLatch是利用外部的线程来协调执行

  3,CyclicBarrier的计数器必须等于线程数,countDownLatch的控制计数器和线程大小没有必然关系

  4,CyclicBarrier可以进行汇总,只需传入barrierAction, countDownLatch执行的时候,不能进行其他的操作,比如汇总计算结果

代码示例

public class CyclicBarrierTest {
	// 自定义工作线程
	private static class Worker extends Thread {
		private CyclicBarrier cyclicBarrier;
		
		public Worker(CyclicBarrier cyclicBarrier) {
			this.cyclicBarrier = cyclicBarrier;
		}
		
		@Override
		public void run() {
			super.run();
			
			try {
				System.out.println(Thread.currentThread().getName() + "开始等待其他线程");
				cyclicBarrier.await();
				System.out.println(Thread.currentThread().getName() + "开始执行");
				// 工作线程开始处理,这里用Thread.sleep()来模拟业务处理
				Thread.sleep(1000);
				System.out.println(Thread.currentThread().getName() + "执行完毕");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
 
	public static void main(String[] args) {
		int threadCount = 3;
		CyclicBarrier cyclicBarrier = new CyclicBarrier(threadCount);
		
		for (int i = 0; i < threadCount; i++) {
			System.out.println("创建工作线程" + i);
			Worker worker = new Worker(cyclicBarrier);
			worker.start();
		}
	}
}

 2,Semaphore

主要做流量控制,协调各个现程,合理利用资源,源码基于AQS实现

场景:数据库连接池,控制某一时刻只有一定数量的连接

使用:创建对象,传入最大同时进行的任务数量,使用时先调用acquirs方法获取‘许可证’,等工作完成之后再调用release方法放回许可证供其他线程使用

注意事项:虽然事先定义了许可证的数量,但是如果不调用acquirs方法,直接调用release方法是允许的,许可证数量也会增加相应数量,会导致许可证数量远大于设定的数量从而导致控流失效

3,Exchange

两个线程之间,对同一类型的数据进行操作,当线程a先执行完,调用exchange方法时等待b线程的执行;线程b的执行完,调用exchange方法时,因为线程a已经等着,此时两个线程进行数据交换,a的数据交给b,b的数据交给a,然后再互相继续执行,数据交换过程线程安全,只支持两个线程

最后修改于 2019-09-06 21:02:21
如果觉得我的文章对你有用,请随意赞赏
扫一扫支付
上一篇