Count_Down

同步工具类 CountDownLatch 和 CyclicBarrier

一曲冷凌霜 提交于 2019-12-05 00:51:38
在开发中,一些异步操作会明显加快执行速度带来更好的体验,但同时也增加了开发的复杂度,想了用好多线程,就必须从这些方面去了解 线程的 wait() notify() notifyall() 方法 线程异步返回 Future ThreadLocal 类 线程池 ThreadPoolExecutor 同步工具类 CountDownLatch , CyclicBarrier , Semaphore , Phaser , Exchanger 估计上面每一个对于 2~3 年的 java 同学来说都是恶梦,比较难以理解,本文简单说下 CountDownLatch 和 CyclicBarrier CountDownLatch CountDownLatch 一般在执行时间较长的可分解的任务中比较常用,算是同步工具类中最容易理解的一个。 示例一: 一个简单的例子:有一个 100 万的 excel 数据导出,需要从数据库中查出数据,并封装成 excel 数据然后输出到前端。 稍微分析可以知道这个操作肯定会很费时间,它的瓶颈出在查询数据库数据和写 excel 上,如果我每 10 万数据一页读数据库并写 excel 成一个文件,最后把所有的 excel 使用 zip 打包,使用多线程,由于读数据库并不会加锁,性能将会有一个量级的提升(有实践过),这时会有一个问题,我启动多个线程后

同步工具类 CountDownLatch 和 CyclicBarrier

喜你入骨 提交于 2019-12-05 00:40:20
在开发中,一些异步操作会明显加快执行速度带来更好的体验,但同时也增加了开发的复杂度,想了用好多线程,就必须从这些方面去了解 线程的 wait() notify() notifyall() 方法 线程异步返回 Future ThreadLocal 类 线程池 ThreadPoolExecutor 同步工具类 CountDownLatch , CyclicBarrier , Semaphore , Phaser , Exchanger 估计上面每一个对于 2~3 年的 java 同学来说都是恶梦,比较难以理解,本文简单说下 CountDownLatch 和 CyclicBarrier CountDownLatch CountDownLatch 一般在执行时间较长的可分解的任务中比较常用,算是同步工具类中最容易理解的一个。 示例一: 一个简单的例子:有一个 100 万的 excel 数据导出,需要从数据库中查出数据,并封装成 excel 数据然后输出到前端。 稍微分析可以知道这个操作肯定会很费时间,它的瓶颈出在查询数据库数据和写 excel 上,如果我每 10 万数据一页读数据库并写 excel 成一个文件,最后把所有的 excel 使用 zip 打包,使用多线程,由于读数据库并不会加锁,性能将会有一个量级的提升(有实践过),这时会有一个问题,我启动多个线程后

学习笔记六:线程间的协作与通信之并发工具类

人走茶凉 提交于 2019-12-03 16:28:13
继续 上一篇 《 学习笔记五:线程间的协作与通信 》 在jdk的并发包里提供了几个非常有用的并发工具类。CountDownLatch、CyclicBarrier和Semaphore工具类提供了一种并发流程控制的手段,Exchanger工具类提供了在线程间交换数据的一种手段,如下主要介绍工具类的使用。 1、等待多线程完成的CountDownLatch CountDownLatch允许一个或多个线程等待其他线程完成操作。 CountDownLatch类实际上是使用计数器的方式去控制的,当我们初始化CountDownLatch的时候传入了一个int变量这个时候在类的内部初始化一个int的变量,每当我们调用countDownt()方法的时候就使得这个变量的值减1,而对于await()方法则去判断这个int的变量的值是否为0,是则表示所有的操作都已经完成,否则继续等待。 构造器中的计数值(count)实际上就是闭锁需要等待的线程数量。计数器的值必须大于等于0,只是等于0的时候,计数器就是零,调用await方法时不会阻塞当前线程;这个值只能被设置一次,而且CountDownLatch没有提供任何机制去重新设置这个计数值;一个线程调用countDown方法happen-before,另外一个线程调用await方法。 与CountDownLatch的第一次交互是主线程等待其他线程

并发编程系列:4大并发工具类的功能、原理、以及应用场景

旧城冷巷雨未停 提交于 2019-12-02 08:31:43
一:并发工具包 1.并发工具类 提供了比synchronized更加高级的各种同步结构:包括CountDownLatch、CyclicBarrier、Semaphore等,可以实现更加丰富的多线程操作。 2.并发容器 提供各种线程安全的容器:最常见的ConcurrentHashMap、ConcurrentSkipListMap,实现线程安全的动态数组CopyOnWriteArrayList等。 3.并发队列 各种BlockingQueue的实现:常用的ArrayBlockingQueue、SynchorousQueue、特定场景的PriorityBlockingQueue。 4.Executor框架 可以创建各种不同类型的线程池,调度任务运行等,绝大部分情况下,不再需要自己从头实现线程池和任务调度器。 二、常见的并发容器 1.ConcurrentHashMap 经常使用的并发容器,JDK 1.7和1.8的底层数据结构发生了变化(后续文章会详解),这里可以建议学习顺序如下:从Java7 HashMap -> Java7 ConcurrentHashMap -> Java8 HashMap -> Java8 ConcurrentHashMap,这样可以更好的掌握这个并发容器,毕竟都是从HashMap进化而来。 2.ConcurrentSkipListMap 在乎顺序

Java多线程同步工具类之CountDownLatch

故事扮演 提交于 2019-12-02 08:31:12
  在过去我们实现多线程同步的代码中,往往使用join()、wait()、notiyAll()等线程间通信的方式,随着JUC包的不断的完善,java为我们提供了丰富同步工具类,官方也鼓励我们使用工具类来实现多线程的同步,今天我们就对其中CountDownLatch类的使用与底层实现进行分析与总结。      一、CountDownLatch使用      CountDownLatch其实可以看做一个计数器,统计多个线程执行完成的情况,适用于控制一个或多个线程等待,直到所有线程都执行完毕的场景,类似与Thread.join()的作用。下面我们通过一个简单的例子看下CountDownLatch的使用。      复制代码      public static void main(String[] args) {      final CountDownLatch countDownLatch = new CountDownLatch(5);      // 启动计数线程      for (int i = 0; i < 5; i++) {      new CountDownLatchThread(i, countDownLatch).start();      }      // 启动等待线程      for (int i = 0; i < 5; i++) {      new

Java中的并发工具类(CountDownLatch、CyclicBarrie、Exchanger)

梦想与她 提交于 2019-12-01 04:45:31
在JDK的并发包里提供了很多有意思的并发工具类。CountDownLatch、CyclicBarrier和Semaphore 工具类提供了一种并发流程控制的手段,Exchanger 工具类则提供了在线程间交换数据的一种手段。 1.等待多线程完成的 CountDownLatch CountDownLatch允许一个或多个线程等待其他线程完成操作。 其实最简单的做噶是使用join()方法,join用于让当前执行线程等待join线程执行结束。其实现原理是不停检查join线程是否存活,如果join线程存活则让当前线程永远等待。其中,wait(0) 表示永远等待下去,代码片段如下: while (isAlive()) { wait(0); } 知道线程中止后,线程的 this.notifyAll() 方法被调用,调用 notifyAll() 方法是在 JVM里实现的,所以在JDK里看不到,大家可以查看JVM源码。 在JDK1.5之后的并发包CountDownLatch也可以实现join的功能,并且功能更多,更强大。 示例代码: 运行结果: 1 2 3 CountDownLatch的构造方法接收一个int类型的参数作为计数器,如果你想等待N个点完成,这里就传入N。 当我们调用CountDownLatch的countDown()方法时,N就会减1,CountDownLatch的 await()

CountDownLatch线程计数器

安稳与你 提交于 2019-11-30 18:56:33
CountDownLatch的使用 概念 countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行。 countDownLatch是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。 使用场景 在一些时候由于数据库连表查询过于缓慢,并且无法在数据库sql层进行优化,这时我们需要在代码中使用线程去分页查询数据,多个线程都执行完毕后将数据封装进一个list再进行返回,这时需要保证所有线程执行完毕后才能返回。 CountDownLatch的使用 // 首先创建一个线程计数器 构造参数为线程数量 CountDownLatch countDownLatch = new CountDownLatch(3); // 创建一个结果集合 List<> list = new ArrayList<>(); // 循环分页查询 for (int i = 1; i <= 3; i++) { // executorService 是一个线程池对象,这里直接使用了,也可以通过new Thread(){ public void run() }.start();匿名内部类方式创建线程 executorService.execute(() -> { // 调用查询

AQS实现之CountDownLatch/Semaphore/CyclicBarrier

≡放荡痞女 提交于 2019-11-30 12:38:47
1 CountDownLatch CountDownLatch是一个计数器闭锁,通过它可以完成类似于阻塞当前线程的功能,即:一个线程或多个线程一直等待,直到其他线程执行的操作完成。 CountDownLatch用一个给定的计数器来初始化,该计数器的操作是原子操作,即同时只能有一个线程去操作该计数器。调用该类await()方法的线程会一直处于阻塞状态,直到其他线程调用countDown()方法使当前计数器的值逐渐减少,到0为止,每次调用countDown计数器的值减1。 当计数器值减至零时,所有因调用await()方法而处于等待状态的线程就会继续往下执行。 这种现象只会出现一次 ,因为计数器不能被重置,如果业务上需要一个可以重置计数次数的版本,可以考虑使用CycliBarrier。 CountDownLatch实现的是AQS的共享锁机制。 CountDownLatch出现以前,类似功能我们使用线程的join()方法实现。 1.1 重要方法 1.1.1 构造器 public CountDownLatch(int count) { if (count < 0) throw new IllegalArgumentException("count < 0"); this.sync = new Sync(count); } Sync(int count) { setState(count);

分布式锁与实现(二)基于ZooKeeper实现

本小妞迷上赌 提交于 2019-11-30 11:24:38
引言 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。 ZooKeeper的架构通过冗余服务实现高可用性。因此,如果第一次无应答,客户端就可以询问另一台ZooKeeper主机。ZooKeeper节点将它们的数据存储于一个分层的命名空间,非常类似于一个文件系统或一个前缀树结构。客户端可以在节点读写,从而以这种方式拥有一个共享的配置服务。更新是全序的。 基于ZooKeeper分布式锁的流程 在zookeeper指定节点(locks)下创建临时顺序节点node_n 获取locks下所有子节点children 对子节点按节点自增序号从小到大排序 判断本节点是不是第一个子节点,若是,则获取锁;若不是,则监听比该节点小的那个节点的删除事件 若监听事件生效,则回到第二步重新进行判断,直到获取到锁 具体实现 下面就具体使用java和zookeeper实现分布式锁,操作zookeeper使用的是apache提供的zookeeper的包。 通过实现Watch接口,实现process(WatchedEvent event)方法来实施监控,使CountDownLatch来完成监控

计数器:CountDownLatch,CountDownLatch,CyclicBarrier

烂漫一生 提交于 2019-11-30 10:45:23
// 创建2个线程的线程池 Executor executor = Executors.newFixedThreadPool(2); while(存在未对账订单){ // 计数器初始化为2 CountDownLatch latch = new CountDownLatch(2); // 查询未对账订单 executor.execute(()->{ pos = getPOrders(); latch.countDown(); }); // 查询派送单 executor.execute(()->{ dos = getDOrders(); latch.countDown(); }); // 等待两个查询操作结束 latch.await(); // 执⾏对账操作 diff = check(pos, dos); // 差异写⼊差异库 save(diff); } 计数器 CountDownLatch: 一个线程等待多个线程。 //定义一个初始值为2的计数器 CountDownLatch latch = new CountDownLatch(2); //计数器-1 latch.countDown(); //线程等待,等待至计数结束。 latch.await(); CyclicBarrier:多个线程相互等待,等待结束执行回调。 //创建一个初始值为2得计数器 CyclicBarrier