使用ExecutorService来停止线程服务
文章目錄
- 使用shutdown
- 使用shutdownNow
使用ExecutorService來停止線程服務(wù)
之前的文章中我們提到了ExecutorService可以使用shutdown和shutdownNow來關(guān)閉。
這兩種關(guān)閉的區(qū)別在于各自的安全性和響應(yīng)性。shutdownNow強行關(guān)閉速度更快,但是風(fēng)險也更大,因為任務(wù)可能正在執(zhí)行的過程中被結(jié)束了。而shutdown正常關(guān)閉雖然速度比較慢,但是卻更安全,因為它一直等到隊列中的所有任務(wù)都執(zhí)行完畢之后才關(guān)閉。
使用shutdown
我們先看一個使用shutdown的例子:
public void useShutdown() throws InterruptedException {ExecutorService executor = Executors.newFixedThreadPool(10);Runnable runnableTask = () -> {try {TimeUnit.MILLISECONDS.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}};executor.submit(runnableTask);executor.shutdown();executor.awaitTermination(800, TimeUnit.MILLISECONDS);}awaitTermination將會阻塞直到所有正在執(zhí)行的任務(wù)完成,或者達到指定的timeout時間。
使用shutdownNow
當(dāng)通過shutdownNow來強行關(guān)閉ExecutorService是, 它會嘗試取消正在執(zhí)行的任務(wù),并返回所有已經(jīng)提交但是還沒有開始的任務(wù)。從而可以將這些任務(wù)保存起來,以便以后進行處理。
但是這樣我們只知道了還沒有開始執(zhí)行的任務(wù),對于那些已經(jīng)開始執(zhí)行但是沒有執(zhí)行完畢卻被取消的任務(wù)我們無法獲取。
我們看下如何獲得開始執(zhí)行但是還沒有執(zhí)行完畢的任務(wù):
public class TrackingExecutor extends AbstractExecutorService {private final ExecutorService executorService;private final Set<Runnable> taskCancelledAtShutdown= Collections.synchronizedSet(new HashSet<Runnable>());public TrackingExecutor(ExecutorService executorService){this.executorService=executorService;}@Overridepublic void shutdown() {executorService.shutdown();}@Overridepublic List<Runnable> shutdownNow() {return executorService.shutdownNow();}@Overridepublic boolean isShutdown() {return executorService.isShutdown();}@Overridepublic boolean isTerminated() {return executorService.isTerminated();}@Overridepublic boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {return executorService.awaitTermination(timeout,unit);}@Overridepublic void execute(Runnable command) {executorService.execute(() -> {try {command.run();}finally {if(isShutdown() && Thread.currentThread().isInterrupted()){taskCancelledAtShutdown.add(command);}}});}public List<Runnable> getCancelledTask(){if(! executorService.isTerminated()){throw new IllegalStateException("executorService is not terminated");}return new ArrayList<>(taskCancelledAtShutdown);} }上面的例子中我們構(gòu)建了一個新的ExecutorService,他傳入一個ExecutorService,并對其進行封裝。
我們重寫了execute方法,在執(zhí)行完畢判斷該任務(wù)是否被中斷,如果被中斷則將其添加到CancelledTask列表中。
并提供一個getCancelledTask方法來返回未執(zhí)行完畢的任務(wù)。
我們看下怎么使用:
public void useShutdownNow() throws InterruptedException {TrackingExecutor trackingExecutor=new TrackingExecutor(Executors.newCachedThreadPool());Runnable runnableTask = () -> {try {TimeUnit.MILLISECONDS.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}};trackingExecutor.submit(runnableTask);List<Runnable> notrunList=trackingExecutor.shutdownNow();if(trackingExecutor.awaitTermination(800, TimeUnit.SECONDS)){List<Runnable> runButCancelledList= trackingExecutor.getCancelledTask();}}trackingExecutor.shutdownNow()返回的是未執(zhí)行的任務(wù)。而trackingExecutor.getCancelledTask()返回的是被取消的任務(wù)。
上面的任務(wù)其實還有一個缺點,因為我們在存儲被取消的任務(wù)列表的額時候taskCancelledAtShutdown.add(command),因為之前的判斷不是原子操作,則可能會產(chǎn)生誤報。
本文的例子請參考https://github.com/ddean2009/learn-java-concurrency/tree/master/ExecutorServiceShutdown
更多內(nèi)容請參考http://www.flydean.com/java-shutdown-executorservice/
總結(jié)
以上是生活随笔為你收集整理的使用ExecutorService来停止线程服务的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 都2020年了,这5个java IDE神
- 下一篇: 万万没想到,线程居然被饿死了!