在第1篇中“并发框架基本示例”,提到了Executors和ThreadPool。
其中,还有个“定时调度”的方法,Executors.newScheduledThreadPool(10)。
// 可执行调度命令(定时+周期性)的线程池,拥有固定的线程数 // 重复执行,无穷尽 public static void scheduledThreadPool() { int initialDelay = 10; int period = 10; Executor executor = Executors.newScheduledThreadPool(10); ScheduledExecutorService scheduler = (ScheduledExecutorService) executor; scheduler.scheduleAtFixedRate(task, initialDelay, period, TimeUnit.SECONDS); }
这段代码,会一直重复执行,是一种常见的场景。
但是,想到一种“只调度N次”的需求,看了下API,没有提供。
就网上搜索“Java 取消线程调度”,找到了1个问答,就研究了下。
代码示例的关键是,使用了线程安全的AtomicInteger和通用同步工具CountDownLatch。
核心逻辑就是,当超过了最大任务数N的时候,取消Future中的任务,countDownLatch中的计数器-1,变为0,“countDownLatch.await()”线程阻塞结束
countDownLatch.countDown();
关于CountDownLatch的进一步介绍,请参考第4篇。
package cn.fansunion.executorframework; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; //有条件地,取消调度 public class ConditionCancelSchedulerDemo { public static Runnable task = new Runnable() { @Override public void run() { System.out.println("Execute a task"); } }; // 可执行调度命令(定时+周期性)的线程池,拥有固定的线程数 // 重复执行,无穷尽 public static void scheduledThreadPool() { int initialDelay = 10; int period = 10; Executor executor = Executors.newScheduledThreadPool(10); ScheduledExecutorService scheduler = (ScheduledExecutorService) executor; scheduler.scheduleAtFixedRate(task, initialDelay, period, TimeUnit.SECONDS); } public static void main(String[] args) throws Exception { scheduledThreadPool(); conditionCancelScheduler(); } private static void conditionCancelScheduler() throws InterruptedException { final String jobID = "my_job_1"; final AtomicInteger count = new AtomicInteger(0); final Map<String, Future> futures = new HashMap<>(); // 最多执行10个任务 final int maxTaskSize = 10; // CountDownLatch的更多用法,请参考CountDownLatchDemo final CountDownLatch countDownLatch = new CountDownLatch(1); ScheduledExecutorService scheduler = Executors .newSingleThreadScheduledExecutor(); Future future = scheduler.scheduleWithFixedDelay(new Runnable() { @Override public void run() { System.out.println(count.getAndIncrement()); // 当调度执行,第maxTaskSize+1个任务的时候,取消Future中的任务。第11个任务 if (count.get() > maxTaskSize) { System.out.println("a"); Future f = futures.get(jobID); if (f != null) { f.cancel(true); } // countDownLatch中的计数器-1,变为0 // “countDownLatch.await()”线程阻塞结束 countDownLatch.countDown(); } } }, 0, 1, TimeUnit.SECONDS); futures.put(jobID, future); countDownLatch.await(); scheduler.shutdown(); } }
更多代码示例:
http://git.oschina.net/fansunion/Concurrent(逐步更新中)
参考资料:
java并发编程-Executor框架
http://www.iteye.com/topic/366591
有条件地终止 ScheduledExecutorService 中运行的定时任务
http://www.oschina.net/question/1158769_119659?sort=time
JDK API 文档