zoukankan      html  css  js  c++  java
  • 多线程分配线程的实现方案:CountDownLatch类

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

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

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

     1 public class CountDownLatchTest {
     2 
     3     static CountDownLatch c = new CountDownLatch(4);
     4 /**线程记录数,当线程开始调用时主线程阻塞,每当一个线程结束时调用countDown()方法,线程记录数减一,当线程记录数为0时,主线程恢复调用。***/
     5 
     6     public static void main(String[] args) throws InterruptedException {
     7         new Thread(new Runnable() {
     8             @Override
     9             public void run() {
    10                 System.out.println(1);
    11                 c.countDown();//记录数减一,3
    12                 System.out.println(2);
    13                 c.countDown();//记录数减一,2
    14                                 System.out.println(3);
    15                 c.countDown();//记录数减一,1
    16                 System.out.println(4);
    17                 c.countDown();//记录数减一,0
    18             }
    19         }).start();
    20 
    21         c.await();
    22         System.out.println("主线程调用");//开始调用日志记录
    23     }
    24 
    25 }                    

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

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

     1     /**
     2      * 单个文件处理入库
     3      * @author yanjp
     4      *
     5      */
     6     class Worker extends Thread{
     7         private DyFile dyFile;
     8         private CountDownLatch ct;
     9         private AnalyzeFileService analyzeFileService;
    10         public Worker(AnalyzeFileService analyzeFileService ,DyFile dyFile,CountDownLatch ct){
    11             this.dyFile=dyFile;
    12             this.ct=ct;
    13             this.analyzeFileService=analyzeFileService;
    14         }
    15         @Override
    16         public void run() {
    17             // TODO Auto-generated method stub
    18             try {
    19                 logger.info("begin入库处理文件:"+dyFile.getFileName());
    20                 //合适的处理器,处理文件.
    21                 analyzeFileService.analyze(dyFile);
    22                 logger.info("end入库处理文件:"+dyFile.getFileName());
    23             } catch (Exception e) {
    24                 // TODO Auto-generated catch block
    25                 logger.error("单个文件入库处理异常",e);
    26             }finally{
    27                 //完成一件任务
    28                 ct.countDown();
    29             }
    30         }
    31         
    32     }

    如果有某个解析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/

  • 相关阅读:
    如何在Eclipse中查看Java类库的源代码以及相应的api
    深入剖析ConcurrentHashMap
    Java7/8 中的 HashMap 和 ConcurrentHashMap 全解析
    Quartz配置
    Spring 自动定时任务配置
    @Resource注解的官方解释
    @Resource 注解的使用
    扫地机器人会否抛弃激光雷达这位原配?
    女教授领军打造最耐用机器人,可从180米高空落下执行救援任务
    一文看懂80年“AI革命”简史
  • 原文地址:https://www.cnblogs.com/0mbiubiu/p/5337005.html
Copyright © 2011-2022 走看看