-
(1) 线程池是线程的所有者,应用程序不是线程的所有者,所以应用程序不能直接停止线程,而是交给线程池处理
(2) 线程池应该提供__生命周期方法__,来关闭自己以及所拥有的线程
(3) __对于持有线程的服务,只要服务的存在时间大于创建线程的方法的存在时间,那么就应该提供生命周期方法
-
关闭ExecutorService
在复杂程序中,通常会将ExecutorService封装在某个高级别的服务中
示例
public class LogService { private final ExecutorService exec = newSingleExecutor(); private final PrintWriter writer; ... public stop() throws InterruptedException { try { exec.shutdown(); exec.awaitTermination(TIMEOUT, UNIT); } finally { writer.close(); } } ... }
awaitTermination()方法:阻塞直到超时或任务都完成
-
shutdownNow()方法的局限性
(1) shutdownNow()方法的返回值是List,它返回的是那些从未开始的任务,而不是完成了一半被迫中止的任务
(2) ExecutorService接口没有提供任何可以返回完成了一半的任务,所以只能自己实现
public class TrackingExecutor extends AbstractExecutorService { private final ExecutorService exec; private final Set<Runnable> tasksCancelledAtShutdown = Collections.synchronizedSet(new HashSet<Runnable>()); ... public List<Runnable> shutdownNow() { return exec.shutdownNow(); } public boolean isShutdown() { return exec.isShutdown(); } public List<Runnable> getCancelledTasks() { if (!exec.isTerminated()) { throw new IllegalStateException(/*...*/); } return new ArrayList<Runnable>(tasksCancelledAtShutdown); } public void execute(final Runnable runnable) { exec.execute(new Runnable() { public void run() { try { runnable.run(); } finally { if (isShutdown() && Thread.currentThread().isInterrupted()) { tasksCancelledAtShutdown.add(runnable); } } } }); } ... }
这里采用的机制是:内部增加一个同步的Set,当当前任务被中断时,判断一下ExecutorService是否被shutdown,如果被shutdown和被中断的条件同时满足,就把当前任务加入Set中,作为getCancelledTasks()的返回值
chapter07_取消与关闭_2_停止基于线程的服务
最新推荐文章于 2022-05-05 08:26:46 发布