java 优雅关闭线程池的方案
我们经常在项目中使用的线程池,但是是否关心过线程池的关闭呢,可能很多时候直接再项目中直接创建线程池让它一直运行当任务执行结束不在需要了也不去关闭,这其实是存在非常大的风险的,大量的线程常驻在后台对系统资源的占用是巨大的,甚至引发异常。所以在我们平时使用线程池时需要注意优雅的关闭,这样可以保证资源的管控。
在Java中和关闭线程池相关的方法主要有如下:
- voidshutdown()
- List
shutDownNow - booleanawaitTermination
- booleanisShutDown
- booleanisTerminated
对于这些方法有着不同的使用和作用,下面我们真的会这些不同的方法做详细的介绍。
ShutDown
shutDown方法从字面意思我们可以看到是停止关闭的意思,我们先来看下面的一段代码,首先我们通过ThreadPoolExecutor来创建一个容量是10的无界线程池,与FixedThreadPool类似的,这里手动创建可以更好地理解线程池的创建。在后我们提交一千个任务执行,再执行shutdown方法进行暂停。
publicstaticvoidmain(String[]args)throwsInterruptedException{ ExecutorServiceservice=newThreadPoolExecutor( 10, 10, 0L, TimeUnit.MILLISECONDS, newLinkedBlockingQueue<>()); for(inti=0;i<1000;i++){ service.submit(()->{ try{ TimeUnit.SECONDS.sleep(1); }catch(InterruptedExceptione){ System.out.println("接受中断,不处理~~"); } System.out.println("args="+Arrays.deepToString(args)+Thread.currentThread().getName()); }); } service.shutdown(); }
- 我们可以看到结果所以线程会正常执行结束后再关闭线程池,对于ShutDown而言它可以安全的停止一个线程池,它有几个关键点
- ShutDown会首先将线程设置成SHUTDOWN状态,然后中断所有没有正在运行的线程
- 正在执行的线程和已经在队列中的线程并不会被中断,说白了就是使用shutDown方法其实就是要等待所有任务正常全部结束以后才会关闭线程池
- 调用shutdown()方法后如果还有新的任务被提交,线程池则会根据拒绝策略直接拒绝后续新提交的任务。
ShutDownNow
这个方法与上面方法相比较,直观就是now,即立即停止任务,
同样是上述案列,略作修改如下,
publicstaticvoidmain(String[]args)throwsInterruptedException{ ExecutorServiceservice=newThreadPoolExecutor( 10, 10, 0L, TimeUnit.MILLISECONDS, newLinkedBlockingQueue<>(1000)); for(inti=0;i<1000;i++){ service.submit(()->{ try{ TimeUnit.SECONDS.sleep(1); }catch(InterruptedExceptione){ System.out.println("接受中断,结束线程~~"); //这里响应中断 return; } System.out.println("args="+Arrays.deepToString(args)+Thread.currentThread().getName()); }); } finalListrunnables=service.shutdownNow(); System.out.println(runnables); }
- 执行上述代码我们发现,当执行shutDownNow方法后,会像全部正在运行的队列通知中断,正在运行的线程接收到中断信号后选择处理,而在队列中的全部取消执行转移到一个list队列中返回,如上述List
runnables,这里记录了所有终止的线程
awaitTermination
- 这个方法并不是用来关闭线程池的,首先我们看一下这个方法的定义:
booleanawaitTermination_(longtimeout,TimeUnitunit)_
- 可以看到这个方法有两个参数,timeout表示等待的时间,unit时间单位
- 这个方法的作用是,调用后等待timeout时间后,反馈线程池的状态,
- 等待期间(包括进入等待状态之前)线程池已关闭并且所有已提交的任务(包括正在执行的和队列中等待的)都执行完毕,相当于线程池已经“终结”了,方法便会返回true;
- 等待超时时间到后,第一种线程池“终结”的情况始终未发生,方法返回false;
- 等待期间线程被中断,方法会抛出InterruptedException异常。
- 上面代码可以修改来测试,这里不再粘贴代码
isShutDown
- isShutDown方法正如名字,判断线程池是否停止,返回的是Boolean类型,如果已经开始停止线程池则返回true否则放回false
- 当调用了shutDown或shutDownNow时之后,会返回true不过需要注意,这时候只是代表线程池关闭流程的开始,并不是说线程池已经停止了
isTerminated
- 这个方法与上面的方法的区别就是这是正真检测线程池是否真的终结了
- 这不仅代表线程池已关闭,同时代表线程池中的所有任务都已经都执行完毕了,因为在调用shutdown方法之后,线程池会继续执行里面未完成的任务,包括正在执行的任务和在任务队列中等待的任务。
- 如果调用了shutdown方法,但是有一个线程依然在执行任务,那么此时调用isShutdown方法返回的是true,而调用isTerminated方法返回的便是false,因为线程池中还有任务正在在被执行,线程池并没有真正“终结”。
- 直到所有任务都执行完毕了,调用isTerminated()方法才会返回true,这表示线程池已关闭并且线程池内部是空的,所有剩余的任务都执行完毕了。
作者:AnonyStar
原文链接:https://www.cnblogs.com/i-code/p/14024845.html
以上就是java优雅关闭线程池的方案的详细内容,更多关于Java关闭线程池的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。