标签:try hex cti get 计时 dex exec 结果 一个
CountDownLatch
Countdownlatch是一个同步工具类;用来协调多个线程之间的同步;
这个工具通常用来控制线程等待;它可以让某一个线程等待知道倒计时结束,在开始执行;
CountDownLatch的两种用法:
1. 某一线程在开始运行前等待n个线程执行完毕;将CountDownLatch的计数器初始化为n:new CountDownLatch(n);每当一个任务线程执行完毕,就将计数器减1,CountDownLatch.Countdown;当计数器的值变为0时;在CountDownLatch上await()的线程就会被唤醒。一个典型应用场景就是启动一个服务时,主线程需要等待多个组件加载完毕;
2. 实现多个线程开始执行任务的最大并行性;注意是并行性;而不是并发性;强调的是多个线程在某一时刻同时执行,类似于赛跑;将多个线程放到起点;等待发令枪响;然后同时开跑;做法是初始化一个共享的CountDownLatch对象;将其计数器初始化为1:new CountdownLatch(1);多个线程在开始执行任务前首先CountDownLatch.await(),当主线程调用countdownl时,计数器变为0;多个线程同时被唤醒;
package com.practice.test; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CountDownLatchExample1 { public static final int threadCount = 550; public static void main(String[] args) throws InterruptedException { ExecutorService threadpool = Executors.newFixedThreadPool(300); final CountDownLatch cl = new CountDownLatch(threadCount); for (int i = 0; i < threadCount; i++) { final int threadnum = i; threadpool.execute(() -> { try { test(threadnum); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { cl.countDown(); } }); } cl.await(); threadpool.shutdown(); System.out.println("finish"); } public static void test(int threadnum) throws InterruptedException { Thread.sleep(1000); System.out.println("threadnum" + threadnum); Thread.sleep(1000); } }
3. Countdownlatch的不足
Countdownlatch是一次性的,计数器的值只能在构造方法中初始化一次,之后没有任何机制再次对其设置值,当CountDownLatch使用完毕后,他不能再次被使用
CyclicBarrier
CyclicBarrier和CountDownLatch非常类似,他也可以实现线程间的技术等待,但是它的功能比CountDownLatch更加强大和复杂。主要应用场景和CountDownLatch类似
CyclicBarrier的字面意思是可循环使用的屏障,它要做的事情是,让一组线程到达一个屏障时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。CyclicBarrier默认的构造方法时CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程调用await方法告诉CyclicBarrier我已经到达了屏障。然后当前线程被阻塞;
package com.practice.test; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class CyclicBarrierExample2 { private static final int threadcount = 550; private static final CyclicBarrier cyb = new CyclicBarrier(5); public static void main(String[] args) throws InterruptedException { ExecutorService threadpool = Executors.newFixedThreadPool(10); for (int i = 0; i < threadcount; i++) { final int num = i; Thread.sleep(1000); threadpool.execute(() -> { try { try { test(num); } catch (TimeoutException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (BrokenBarrierException e) { // TODO Auto-generated catch block e.printStackTrace(); } }); } threadpool.shutdown(); } public static void test(int threadnum) throws InterruptedException, BrokenBarrierException, TimeoutException { System.out.println("threadnum" + threadnum + "is ready"); try { cyb.await(2000, TimeUnit.MILLISECONDS); } catch (Exception e) { System.out.println("CyclicBarrier"); } System.out.println("threadnum" + threadnum + "isFinish"); } }
CyclicBarrier的应用场景
CyclicBarrier可以用于多线程计算数据,最后合并结果的应用场景。比如我们用一个Excel保存了用户所有银行流水,每个Sheet保存每一个账户近一年的每一笔银行流水,现在需要统计用户的日均银行流水,先用多线程处理每个sheet里的银行流水,都执行完之后,得到每个sheet的日均银行流水,最后,使用barrierAction用这些线程的计算结果,计算出整个Excel的日均银行流水;
CyclicBarrier(int parties,Runnable BarrierAction),在线程到达屏障时,优先执行BarrierAction,方便处理更复杂的业务场景;
package com.practice.test; import java.util.concurrent.CyclicBarrier; public class CyclicBarrierTest { public static void main(String[] args) { CyclicBarrier cyl = new CyclicBarrier(5, () -> { System.out.println("线程组执行结束"); }); for (int i = 0; i < 5; i++) { new Thread(new Readnum(i, cyl)).start(); } } static class Readnum implements Runnable { private int id; private CyclicBarrier cdl; public Readnum(int id, CyclicBarrier cdl) { super(); this.id = id; this.cdl = cdl; } @Override public void run() { synchronized (this) { System.out.println(Thread.currentThread().getName() + "id"); try { cdl.await(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + id + "结束了"); } } } }
CyclicBarrier和CountDownLatch的区别
CountDownLatch是计数器,只能使用一次,而CyclicBarrier的计数器提供reset功能,可以多次使用,
JavaDoc中的定义:
CountDownLatch:一个或者多个线程,等待其他线程完成某件事情之后,等待其他多个线程完成某件事情之后才能执行;
CyclicBarrier:多个线程互相等待,直到到达同一个同步点,再继续一起执行;
对于CountDownLatch来说,重点是一个线程(多个线程)等待”,而其他的N个线程在完成”某件事情“之后,可以终止,也可以等待,而对于CyclicBarrier,重点是多个线程,在任意一个线程没有完成,所有的线程都必须等待;
CountDownLatch是计数器,线程完成一个记录一个,只不过计数不是递增而是递减,而CyclicBarrier更像是一个阀门,需要所有线程都要到达,阀门才能打开,然后继续执行;
文章参考自:
https://github.com/Snailclimb
https://blog.csdn.net/tolcf/article/details/50925145?utm_source=blogxgwz0
CyclicBarrier和CountDownLatch的区别
标签:try hex cti get 计时 dex exec 结果 一个
原文地址:https://www.cnblogs.com/yjxs/p/9911903.html