需求:假如我们本地有4个文件需要解析,每个文件的内容为20万行。为了提高效率我们要创建4个线程进行处理。等4个线程处理完,要在文件日志表中记录处理状态。

一般的的解决方法是使用join,join用于让当前执行线程等待join线程执行结束。其实现原理是不停检查join线程是否存活,如果join线程存活则让当前线程永远wait。直到join线程中止后,线程的this.notifyAll会被调用。

但是DK1.5之后的并发包中提供的CountDownLatch也可以实现join的这个功能,并且比join的功能更多。

 public class CountDownLatchTest {

     static CountDownLatch c = new CountDownLatch(4);
/**线程记录数,当线程开始调用时主线程阻塞,每当一个线程结束时调用countDown()方法,线程记录数减一,当线程记录数为0时,主线程恢复调用。***/ public static void main(String[] args) throws InterruptedException {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(1);
c.countDown();//记录数减一,3
System.out.println(2);
c.countDown();//记录数减一,2
System.out.println(3);
c.countDown();//记录数减一,1
System.out.println(4);
c.countDown();//记录数减一,0
}
}).start(); c.await();
System.out.println("主线程调用");//开始调用日志记录
} }

CountDownLatch的构造函数接收一个int类型的参数作为计数器,如果你想等待N个点完成,这里就传入N。

当我们调用一次CountDownLatch的countDown方法时,N就会减1,CountDownLatch的await会阻塞当前线程,直到N变成零。由于countDown方法可以用在任何地方,所以这里说的N个点,可以是N个线程,也可以是1个线程里的N个执行步骤。用在多个线程时,你只需要把这个CountDownLatch的引用传递到线程里。

     /**
* 单个文件处理入库
* @author yanjp
*
*/
class Worker extends Thread{
private DyFile dyFile;
private CountDownLatch ct;
private AnalyzeFileService analyzeFileService;
public Worker(AnalyzeFileService analyzeFileService ,DyFile dyFile,CountDownLatch ct){
this.dyFile=dyFile;
this.ct=ct;
this.analyzeFileService=analyzeFileService;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
logger.info("begin入库处理文件:"+dyFile.getFileName());
//合适的处理器,处理文件.
analyzeFileService.analyze(dyFile);
logger.info("end入库处理文件:"+dyFile.getFileName());
} catch (Exception e) {
// TODO Auto-generated catch block
logger.error("单个文件入库处理异常",e);
}finally{
//完成一件任务
ct.countDown();
}
} }

如果有某个解析sheet的线程处理的比较慢,我们不可能让主线程一直等待,所以我们可以使用另外一个带指定时间的await方法,await(long time, TimeUnit unit): 这个方法等待特定时间后,就会不再阻塞当前线程。join也有类似的方法。

注意:计数器必须大于等于0,只是等于0时候,计数器就是零,调用await方法时不会阻塞当前线程。CountDownLatch不可能重新初始化或者修改CountDownLatch对象的内部计数器的值。一个线程调用countDown方法 happen-before 另外一个线程调用await方法。

CountDownLatch的一个非常典型的应用场景是:有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以继续往下执行。假如我们这个想要继续往下执行的任务调用一个CountDownLatch对象的await()方法,其他的任务执行完自己的任务后调用同一个CountDownLatch对象上的countDown()方法,这个调用await()方法的任务将一直阻塞等待,直到这个CountDownLatch对象的计数值减到0为止。

参考:

http://ifeve.com/talk-concurrency-countdownlatch/

多线程分配线程的实现方案:CountDownLatch类的更多相关文章

  1. 关于Unity中协程、多线程、线程锁、www网络类的使用

    协程 我们要下载一张图片,加载一个资源,这个时候一定不是一下子就加载好的,或者说我们不一定要等它下载好了才进行其他操作,如果那样的话我就就卡在了下载图片那个地方,傻住了.我们希望我们只要一启动加载的命 ...

  2. 多线程-2.线程创建方式和Thread类

    线程的创建方式 1.继承Thread类,重写run方法,示例如下: 1 class PrimeThread extends Thread { 2 long minPrime; 3 PrimeThrea ...

  3. java核心-多线程(4)-线程类基础知识

    1.并发 <1>使用并发的一个重要原因是提高执行效率.由于I/O等情况阻塞,单个任务并不能充分利用CPU时间.所以在单处理器的机器上也应该使用并发. <2>为了实现并发,操作系 ...

  4. java多线程等待协调工作:CountDownLatch类的高级应用

    一:说明 基本上对于线程初步了解的人,都是使用synchronized来同步线程的,也确实,它也是可以满足一些常用的问题.那么我们来说一些它不能解决的问题(其实是不怎么好解决的问题,并不是真的不能解决 ...

  5. JAVA与多线程开发(线程基础、继承Thread类来定义自己的线程、实现Runnable接口来解决单继承局限性、控制多线程程并发)

    实现线程并发有两种方式:1)继承Thread类:2)实现Runnable接口. 线程基础 1)程序.进程.线程:并行.并发. 2)线程生命周期:创建状态(new一个线程对象).就绪状态(调用该对象的s ...

  6. Java基础学习笔记: 多线程,线程池,同步锁(Lock,synchronized )(Thread类,ExecutorService ,Future类)(卖火车票案例)

    多线程介绍 学习多线程之前,我们先要了解几个关于多线程有关的概念.进程:进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能. 线 ...

  7. python 多线程编程之threading模块(Thread类)创建线程的三种方法

    摘录 python核心编程 上节介绍的thread模块,是不支持守护线程的.当主线程退出的时候,所有的子线程都将终止,不管他们是否仍在工作. 本节开始,我们开始介绍python的另外多线程模块thre ...

  8. 【Java多线程】JUC包下的工具类CountDownLatch、CyclicBarrier和Semaphore

    前言 JUC中为了满足在并发编程中不同的需求,提供了几个工具类供我们使用,分别是CountDownLatch.CyclicBarrier和Semaphore,其原理都是使用了AQS来实现,下面分别进行 ...

  9. Java多线程之线程其他类

    Java多线程之线程其他类 实际编码中除了前面讲到的常用的类之外,还有几个其他类也有可能用得到,这里来统一整理一下: 1,Callable接口和Future接口 JDK1.5以后提供了上面这2个接口, ...

随机推荐

  1. Delphi CreateFile函数

  2. python面向编程:类的组合、封装、property装饰器、多态

    一.组合 二.封装 三.propert装饰器 四.多态 一.组合 ''' 1. 什么是组合 一个对象的属性是来自于另外一个类的对象,称之为组合 2. 为何用组合 组合也是用来解决类与类代码冗余的问题 ...

  3. Android异常与性能优化相关面试问题-ui卡顿面试问题详解

    UI卡顿原理: “60fps(Frames Per Second每秒传输帧数) ----> 16ms” 针对上面标红的数字,下面具体说明一下:最主要的根源在于渲染性,Android会每隔16ms ...

  4. jenkins+docker+docker-compose持续集成

    一.前期准备 1.宿主机安装docker,传送门 2.宿主机安装JDK,传送门 3.宿主机安装maven,传送门 4.宿主机安装git yum install git 5.宿主机安装jenkins,传 ...

  5. 数据库允许空值(null),往往是悲剧的开始(1分钟系列)

    数据库字段允许空值,会遇到一些问题,此处包含的一些知识点,和大家聊一聊. 数据准备: create table user ( id int, name varchar(20), index(id) ) ...

  6. golang-vue实现微信小程序分享到朋友圈

    最近涉及到微信小程序分享到朋友圈,不知道微信为什么不直接接口分享,咱也不敢佛,咱也不敢问,只能百度问度娘,看官方文档,网上的一些分享五花八门,每一个重点的,所以整理了一下到底怎样生成二维码分享图片才是 ...

  7. Linux之more命令

    命令解释 more命令类似与cat命令,却比cat命令强大,它以全屏幕的方式按页显示文本文件的内容,支持vi中的关键字定位操作. 命令说明 more [选项] 文件.. 命令选项 -d    显示帮助 ...

  8. 给零基础的小白从0到1的react-naitve电商app——简单易学!

    先上链接https://github.com/duf1991/DY...我的第一个react-native学习成果,欢迎各位大佬star和issue!

  9. return new Promise的时候,不能带着.then()方法

    app.js return new Promise的同时带着.then()方法会出错 return出去的这个Promise,整体状态会显示pending,虽然详细里状态显示resolve,但是没有re ...

  10. Ubuntu下python开发环境搭建

    配置语言 1) 依次点击设置--Region & Language--Manage Installed Languages --install/remove language--chinese ...