java开发-批量线程同步

来源:互联网 发布:二维码扫描价格软件 编辑:程序博客网 时间:2024/05/17 09:44

问题背景描述

启用线程池批量执行一些定时任务,每次需要这些任务都执行完,再开始下一次的任务批量执行。
如下图:
这里写图片描述

如上图的业务描述,如果不对批量的线程任务做原子性限制,假如第一次执行定时任务,某条线程任务执行的比较慢,8分钟了还没执行完。第二次执行定时任务时,由于该条任务数据库数据状态没有改变,还会被读取出来,导致重复执行。所以,需要对每次定时任务的这些批量任务加原子性限制,只有当前这次的批量任务都做完了,才能开始下一次批量任务。

解决方案

使用CountDownLatch工具类,可以实现“批量线程”同步。
CountDownLatch类可以通过await()方法,让当前线程处于一直阻塞等待状态,直到通过countDown() 方法将线程的计数器减为0。在初始化CountDownLatch时,指定线程计数总数。

public void executor() {        System.out.println("---------任务调度开始-------------");        CountDownLatch latch = new CountDownLatch(3);        for (TSysTask taskInfo : taskList) {            AbstractSysTask task = new MyTask();            sysTaskThreadPool.execute(task);        }        System.out.println("---------任务调度中-------------");        try {            latch.await();        } catch (InterruptedException e) {            logger.error(e.getMessage(), e);        System.out.println("---------任务调度结束-------------");    }

分析:
(1)只有通过调用 latch.await() 方法才会实现“批量线程”同步;不调用这个方法,是没有任何效果的;
也就是说,即便初始化时指定了计数器个数,如果不调用 latch.await() 方法,怎么调用countDown方法都没用的。
(2)调用 latch.await() 方法,CountDownLatch工具类会立刻将当前方法 executor 锁定给当前线程,此时别的其他线程是无法执行executor方法的,得排队等着。直到通过countDown方法将同步计数器减为0.
(3)调用 latch.await() 方法,当前线程会立刻处于类似sleep的状态,直到同步计数器减为0。也就是说, latch.await() 方法后面的代码不会被执行,直到同步计数器减为0。
(4)CountDownLatch 机制不是用来保护共享资源或者临界区。它是用来同步一个或者多个线程。它只能使用一次。也就是说,一旦CountDownLatch的计数器到达0,任何对它的方法的调用都是无效的。如果你想再次同步,你必须创建新的对象。

原创粉丝点击