Java线程池详细介绍

  

这篇文章主要介绍“Java线程池详细介绍”,在日常操作中,相信很多人在Java线程池详细介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java线程池详细介绍”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

之所以要使用线程池,是因为使用new Thread在大型项目中是有弊端的:

  1. 每次new Thread新建对象,性能差

  2. 线程缺乏统一管理,可能无限制的新建线程,相互竞争,有可能会造成过多占用系统资源而导致OOM

  3. 缺少更多功能,如定期执行等

而线程池的好处:

  1. 重用存在的线程,减少对象创建、消亡的开销,性能佳

  2. 可有效控制最大并发线程数,提高系统资源利用率,同时可以避免过多资源竞争,避免阻塞

  3. 提供定时执行、定期执行、单线程、并发数控制等功能

状态池的状态转换

Java线程池详细介绍

线程池的类继承关系

  1. Executor是一个顶层接口,在它里面只声明了一个方法execute(Runnable),返回值为void,参数为Runnable类型,从字面意思可以理解,就是用来执行传进去的任务的

  2. ExecutorService接口继承了Executor接口,并声明了一些方法:submit、invokeAll、invokeAny以及shutDown等

  3. 抽象类AbstractExecutorService实现了ExecutorService接口,基本实现了ExecutorService中声明的所有方法

  4. ThreadPoolExecutor继承了类AbstractExecutorService。

ThreadPoolExecutor的方法说明

  1. execute()实际上是Executor中声明的方法,在ThreadPoolExecutor进行了具体的实现,这个方法是ThreadPoolExecutor的核心方法,通过这个方法可以向线程池提交一个任务,交由线程池去执行

  2. submit()方法是在ExecutorService中声明的方法,在AbstractExecutorService就已经有了具体的实现,在ThreadPoolExecutor中并没有对其进行重写,这个方法也是用来向线程池提交任务的,但是它和execute()方法不同,它能够返回任务执行的结果,去看submit()方法的实现,会发现它实际上还是调用的execute()方法,只不过它利用了Future来获取任务执行结果

  3. shutdown()优雅关闭线程池

  4. shutdownNow()强制关闭线程池

还有很多其他的方法:比如:getQueue() 、getPoolSize() 、getActiveCount()、getCompletedTaskCount()等获取与线程池相关属性的方法,可以用于线程池监控,有兴趣的朋友可以自行查阅API。

更多ThreadPoolExecutor配置的详细说明,点击查看:还在用Executors创建线程池?小心内存溢出

ScheduledExecutorService使用说明

@Slf4jpublic class ThreadPoolExample {
  ,公共静态void main (String [] args){ <代码>
<代码>,,,,ScheduledExecutorService executorService=Executors.newScheduledThreadPool(1); <代码>
<代码>,,,,//延时任务 <代码>//,,,,executorService.schedule(()→ <代码>//,,,,,,,,log.warn(“时间表run"), 3, TimeUnit.SECONDS); <代码>
<代码>,,,,//固定速率任务 <代码>,,,代码,executorService.scheduleAtFixedRate(() <代码>,,,,,,,,→log.warn(“时间表run"), 1, 3, TimeUnit.SECONDS); <代码>//,,,代码,executorService.shutdown(); <代码>
<代码>,,,,//计时器也能执行定时任务,不过还是推荐用ScheduledExecutorService <代码>//,,,计时器,计时器=new计时器(); <代码>//,,,计时器。日程安排(新TimerTask(){ <代码>//,,,,,代码,@Override <代码>//,,,,,,公共空间run(){ <代码>//,,,,,,,,log.warn(“计时器run"); <代码>//,,,,,代码,} <代码>//,,,},新的日期(),5 * 1000); <代码>,,} <代码>}
  

特别提示:通过ScheduledExecutorService执行的周期任务,如果任务执行过程中抛出了异常,那么ScheduledExecutorService就会停止执行任务,而且也不会再周期地执行该任务了。所以如果想保持任务周期执行,需要抓一切可能的异常。

线程池核心线程数配置推荐

CPU密集型任务:尽量压榨CPU、参考值设置为NCPU + 1

Java线程池详细介绍