JAVA多线程系列--并发工具类(CountDownLatch, CyclicBarrier, Semaphore,Exchanger)
2017-12-14 19:10
1341 查看
前言
本节笔者将详细讲下CountDownLatch, CyclicBarrier, Semaphore,Exchanger 这四个并发工具类的使用。这4个工具类在高并发的场景下,也是使用广泛。
1.1 CountDownLatch简介
CountDownLatch是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行。1.2 CountDownLatch使用场景
1.实现最大的并行性:有时我们想同时启动多个线程,实现最大程度的并行性。例如,我们想测试一个单例类。如果我们创建一个初始计数为1的CountDownLatch,并让所有线程都在这个锁上等待,那么我们可以很轻松地完成测试。我们只需调用 一次countDown()方法就可以让所有的等待线程同时恢复执行。 2.开始执行前等待n个线程完成各自任务:例如应用程序启动类要确保在处理用户请求前,所有N个外部系统已经启动和运行了。 3.死锁检测:一个非常方便的使用场景是,你可以使用n个线程访问共享资源,在每次测试阶段的线程数目是不同的,并尝试产生死锁。
1.3CountDownLatch 例子
/** * CountDownLatch * @author niyuelin * */ public class CountDownLatchDemo { final static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static void main(String[] args) throws InterruptedException { CountDownLatch latch = new CountDownLatch(2);// 两个工人的协作 Worker worker1 = new Worker("zhang san", 5000, latch); Worker worker2 = new Worker("li si", 1000, latch); worker1.start();// worker2.start();// latch.await();// 等待所有工人完成工作 System.out.println("all work done at " + sdf.format(new Date())); } static class Worker extends Thread { String workerName; int workTime; CountDownLatch latch; public Worker(String workerName, int workTime, CountDownLatch latch) { this.workerName = workerName; this.workTime = workTime; this.latch = latch; } public void run() { System.out.println("Worker " + workerName + " do work begin at " + sdf.format(new Date())); doWork();// 工作了 System.out.println("Worker " + workerName + " do work complete at " + sdf.format(new Date())); latch.countDown();// 工人完成工作,计数器减一 } private void doWork() { try { Thread.sleep(workTime); } catch (InterruptedException e) { e.printStackTrace(); } } } }
1.4 输出结果
Worker li si do work begin at 2017-12-14 18:52:46 Worker zhang san do work begin at 2017-12-14 18:52:46 Worker li si do work complete at 2017-12-14 18:52:47 Worker zhang san do work complete at 2017-12-14 18:52:51 all work done at 2017-12-14 18:52:51
2.1 CyclicBarrier简介
CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程调用await方法告诉CyclicBarrier我已经到达了屏障,然后当前线程被阻塞。
2.2 CyclicBarrier使用场景
CyclicBarrier可以用于多线程计算数据,最后合并计算结果的应用场景
2.3 CyclicBarrier例子
/** * CyclicBarrier * @author niyuelin * */ public class CyclicBarrierDemo2 { public static void main(String[] args) { int N = 4; CyclicBarrier barrier = new CyclicBarrier(N, new Runnable() { @Override public void run() { System.out.println("当前线程" + Thread.currentThread().getName()); } }); for (int i = 0; i < N; i++) new Writer(barrier).start(); } static class Writer extends Thread { private CyclicBarrier cyclicBarrier; public Writer(CyclicBarrier cyclicBarrier) { this.cyclicBarrier = cyclicBarrier; } @Override public void run() { System.out.println("线程" + Thread.currentThread().getName() + "正在写入数据..."); try { Thread.sleep(5000); // 以睡眠来模拟写入数据操作 System.out.println("线程" + Thread.currentThread().getName() + "写入数据完毕,等待其他线程写入完毕"); cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } System.out.println("所有线程写入完毕,继续处理其他任务..."); } } }
2.4 输出结果
线程Thread-0正在写入数据... 线程Thread-1正在写入数据... 线程Thread-3正在写入数据... 线程Thread-2正在写入数据... 线程Thread-3写入数据完毕,等待其他线程写入完毕 线程Thread-0写入数据完毕,等待其他线程写入完毕 线程Thread-1写入数据完毕,等待其他线程写入完毕 线程Thread-2写入数据完毕,等待其他线程写入完毕 当前线程Thread-1 所有线程写入完毕,继续处理其他任务... 所有线程写入完毕,继续处理其他任务... 所有线程写入完毕,继续处理其他任务... 所有线程写入完毕,继续处理其他任务...
3.1 Semaphore简介
Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。Semaphore可以控同时访问的线程个数,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。
3.2 Semaphore使用场景
1.流量控制,特别公用资源有限的应用场景,比如数据库连接 2.对某组资源的访问权限
3.3 Semaphore例子
/** * Semaphore * @author niyuelin * */ public class SemaphoreTest { private static final int THREAD_COUNT = 30; private static ExecutorService executorService = Executors.newFixedThreadPool(30); private static Semaphore s = new Semaphore(10); private static int in = 0; public static synchronized void add(){ in++; } public static void main(String[] args) throws InterruptedException { for(int i =0; i<THREAD_COUNT; i++){ executorService.execute(new Runnable() { public void run() { try { s.acquire(); Thread.sleep(1000); add(); // System.out.println("save data"); s.release(); } catch (InterruptedException e) { e.printStackTrace(); } } }); } Thread.sleep(1500); System.out.println(in); Thread.sleep(1000); System.out.println(in); executorService.shutdown(); } }
3.4 输出结果
10 29
4.1 Exchanger简介
Exchanger(交换者)是一个用于线程间协作的工具类。Exchanger用于进行线程间的数据交换。它提供一个同步点,在这个同步点两个线程可以交换彼此的数据。这两个线程通过exchange方法交换数据, 如果第一个线程先执行exchange方法,它会一直等待第二个线程也执行exchange,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方。4.2 Exchanger使用场景
1.遗传算法,遗传算法里需要选出两个人作为交配对象,这时候会交换两人的数据,并使用交叉规则得出2个交配结果。 2.校对工作 我们需要将纸制银流通过人工的方式录入成电子银行流水,为了避免错误,需要两个线程相互校对。
4.3 Exchanger例子
/** * Exchanger * @author niyuelin * */ public class ExChangerTest { private static final Exchanger<String> exgr = new Exchanger<String>(); private static ExecutorService executorService = Executors.newFixedThreadPool(2); public static void main(String[] args) { executorService.execute(new Runnable() { @Override public void run() { try { String A = "银行流水A"; String c = exgr.exchange(A); System.out.println("c: "+ c); } catch (InterruptedException e) { e.printStackTrace(); } } }); executorService.execute(new Runnable() { public void run() { try { String B = "银行流水B"; String A = exgr.exchange(B); System.out.println("A:"+A+" ,B:"+B); } catch (InterruptedException e) { e.printStackTrace(); } } }); executorService.shutdown(); } }
4.4 输出结果
c:银行流水B A:银行流水A ,B:银行流水B
相关文章推荐
- 四个并发工具类CountDownLatch,CyclicBarrier,Semaphore,Exchanger
- 第8章 Java中的并发工具类(CountDownLatch CyclicBarrier Semaphore Exchanger)
- Java并发编程之2——同步工具类的使用(CountDownLatch,CyclicBarrier,BlockungQueue,Semaphore)
- 《Java 7 并发编程指南》学习概要 (3)Semaphore, CountDownLatch, CyclicBarrier , Phaser, Exchanger
- Java中的并发工具类:CountDownLatch、CyclicBarrier和Semaphore
- Java_并发线程_Semaphore、CountDownLatch、CyclicBarrier、Exchanger
- Java线程(CountDownLatch、CyclicBarrier、Semaphore)并发控制工具类
- 并发工具类CountDownLatch、CyclicBarrier、Semaphore、Exchanger详解
- 并发工具类:CountDownLatch、CyclicBarrier、Semaphore
- Java并发:同步工具类详解(CountDownLatch、CyclicBarrier、Semaphore)
- 并发包下常见的同步工具类详解(CountDownLatch,CyclicBarrier,Semaphore)
- java并发编程——八 理解分析并发组件-CountDownLatch\CyclicBarrier\Exchanger\Semaphore
- Java_并发线程_Semaphore、CountDownLatch、CyclicBarrier、Exchanger
- 多线程并发常用类:condition,semaphore,CyclicBarrier,countdownlatch,exchanger使用整理
- Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
- Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
- java并发编程:CountDownLatch、CyclicBarrier和Semaphore
- 多线程编程的常用类(CountDownLatch, Semaphore, CyclicBarrier 和 Exchanger)
- JAVA并发CountDownLatch、CyclicBarrier、Semaphore