CountDownLatch在多线程处理任务中的实践

前言

之前语音资源部需要下载一批音频,当时开发一个多线程下载工具,其中多线程处理逻辑,就是将一批任务分配给多个线程去处理,其实代码简化下来就是用多线程处理一个list。

简化代码

public class HandleThread extends Thread {

    private static final Log LOGGER = LogFactory.getLog(HandleThread.class);
    private String threadName;
    private List<String> data;
    private int start;
    private int end;
    private CountDownLatch CountDownLatch;

    public HandleThread(String threadName, List<String> data, int start, int end,
    CountDownLatch countDownLatch) {
        this.threadName = threadName;
        this.data = data;
        this.start = start;
        this.end = end;
        this.countDownLatch=countDownLatch;
    }

    public void run() {
        List<String> subList = data.subList(start, end);
        LOGGER.info(threadName + "处理了" + subList.size() + "条!");
        //具体的下载逻辑
        down(subList);
        //当前线程处理完之后计数器减一
        countDownLatch.countDown()
    }
}

具体的任务分配逻辑

    /**
     * 一批任务,分配n个线程去处理
     * @param data
     * @param threadNum
     */
    public synchronized void handleList(List<String> data, int threadNum) {
        if (CollectionUtils.isEmpty(data)) {
            return;
        }
        //初始化一个计数器
        CountDownLatch countDownLatch = new CountDownLatch(threadNum);
        int length = data.size();
        int tl = length % threadNum == 0 ? length / threadNum : (length
                / threadNum + 1);

        for (int i = 0; i < threadNum; i++) {
            int end = (i + 1) * tl;
            HandleThread thread = new HandleThread("线程[" + (i + 1) + "] ",
                    data, i * tl, end > length ? length : end, countDownLatch);
            thread.start();
        }
        
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        LOGGER.info("所有音频下载完成");
    }

CountDownLatch和join的区别

  • countDownLatch 原理:可以理解为一个计数器。在初始化 CountDownLatch 的时候会在类的内部初始化一个int的变量,每当调用 countDownt() 方法的时候这个变量的值减1,而 await() 方法就是去判断这个变量的值是否为0,是则表示所有的操作都已经完成,否则继续等待。
  • join 原理:在当前线程中调用另一个线程线程 thread 的 join() 方法时,会调用该 thread 的 wait() 方法,直到这个 thread 执行完毕(JVM在 run() 方法执行完后调用 exit() 方法,而 exit() 方法里调用了 notifyAll() 方法)会调用 notifyAll() 方法主动唤醒当前线程。
  • join和countDownLatch都能实现让当前线程阻塞等待其他线程执行完毕,join使用起来更简便,不过countDownLatch粒度更细。不需要一定将线程里面所有任务都完成之后再进行计数器减一,我们可以细粒度的控制到任务的环节。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值