zoukankan      html  css  js  c++  java
  • Java之CountDownLatch ---控制线程执行顺序

    一,类介绍

    这是java.util.concurrent包里的一个同步辅助类,它有两个主要的常用方法  countDown()方法以及await()方法。在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

    这个类可以帮助我们做什么事呢?

    二,实例运行

    列举一个场景,三个人赛跑,哨声一响同时出发,跑到一半时A选手突然觉得拿名次没什么意思,当最后一名也挺好,然后他就让B,C先跑到终点,然后自己再跑。

    这里我们可以开三个线程模拟三位选手,看看我们怎么通过这两个重要方法来实现A选手的想法的。

    代码如下,不妨先复制一下,跑起来再说。

    public class Sample {
    
            /**
             * 计数器,用来控制线程
             * 传入参数2,表示计数器计数为2
             */
            private final static CountDownLatch mCountDownLatch = new CountDownLatch(2);
            
            /**
             * A线程类
             */
            private static class ThreadA extends Thread {
                
                @Override
                public void run() {
                    System.out.println("A选手  出发!");
                    try {
                        // 会阻塞在这里等待 mCountDownLatch 里的count变为0;
                        // 也就是等待另外的WorkingThread调用countDown()
                        mCountDownLatch.await();
                    } catch (InterruptedException e) {
                        
                    }
                    System.out.println("A选手  到终点拉!");
                }
            }
            
            /**
             * BC线程类
             */
            private static class WorkingThread extends Thread {
                private final String mThreadName;
                private final int mSleepTime;
                public WorkingThread(String name, int sleepTime) {
                    mThreadName = name;
                    mSleepTime = sleepTime;
                }
                
                @Override
                
                public void run() {
                    System.out.println("[" + mThreadName + "] 出发!");
                    try {  
                            Thread.sleep(mSleepTime);  
                    } catch (InterruptedException e) {  
                            e.printStackTrace();  
                    }
             
                    System.out.println("[" + mThreadName + "] 到终点拉!"); 
                    mCountDownLatch.countDown();
                }
            }
            
            public static void main(String[] args) throws Exception {
                // 最先run ThreadA
                new ThreadA().start();
                
                new WorkingThread("B选手", 2000).start();
             
                new WorkingThread("C选手", 2000).start();
           
            }
        
    }

     

    三,代码分析

    现在我们来分析一下代码,我们先开启了A线程,它先跑了,但是在A线程的run方法中,调用了await()方法,这个方法可以让当前线程处于等待状态,直到计数器为0时,才继续往下执行。

    好了计数器是什么东西,其实CountDownLatch这个类我们就可以把它看出一个计数器,实际上它内部也真实维护了一个count计数,对计数的操作都是原子的,啰嗦一句,原子操作的意思

    就是当一个线程对count进行修改时,其他的线程是不可以同时修改的。上面说到要等到计数器为0才行,显然想让它为0,就得有个初始值,然后再有减的操作才行吧。赋初始值的操作,就是new这

    个对象的时候就完成拉,代码中 new CountDownLatch(2) 就是给count设为2的操作,然后mCountDownLatch.countDown()这个方法就是count减去1的操作,代码我们减了两次,为0之后,A选手才继续跑完。

    好了,这样的栗子好像只能帮助理解,但是挑不起兴趣,再举一个工作中真实用到的场景。

    开启多个线程分块下载一个大文件,每个线程只下载固定的一截,最后由另外一个线程来拼接所有的分段,那么这时候我们可以考虑使用CountDownLatch来控制并发,使得拼接的线程放在最后执行。

  • 相关阅读:
    POJ 3071 概率DP
    BZOJ 2427 /HAOI 2010 软件安装 tarjan缩点+树形DP
    POJ 1155 树形DP
    POJ 3252 组合数学?
    POJ 3641 快速幂
    POJ 3180 Tarjan
    POJ 3185 DFS
    POJ 3260 DP
    POJ 2392 DP
    99. Recover Binary Search Tree
  • 原文地址:https://www.cnblogs.com/xinde123/p/7884973.html
Copyright © 2011-2022 走看看