快速了解Java线程池

栏目: Java · 发布时间: 5年前

内容简介:之所以要使用线程池,是因为使用new Thread在大型项目中是有弊端的:而线程池的好处:

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

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

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

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

而线程池的好处:

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

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

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

状态池的状态转换

快速了解 <a href='https://www.codercto.com/topics/22013.html'>Java</a> 线程池

线程池的类继承关系

快速了解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使用说明


 

@Slf4j

public class ThreadPoolExample {


public static void main(String[] args) {


ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);


// 延时任务

// executorService.schedule(()->

// log.warn("schedule run"), 3, TimeUnit.SECONDS);


// 固定速率任务

executorService.scheduleAtFixedRate(()

-> log.warn("schedule run"), 1, 3, TimeUnit.SECONDS);

// executorService.shutdown();


// Timer也能执行定时任务,不过还是推荐用ScheduledExecutorService

// Timer timer = new Timer();

// timer.schedule(new TimerTask() {

// @Override

// public void run() {

// log.warn("timer run");

// }

// }, new Date(), 5 * 1000);

}

}

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

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

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

IO密集型任务:参考值可以设置为2*NCPU

相关的线程池

Spring的异步线程池

TaskExecutor是Spring异步线程池的接口,继承Java.util.concurrent.Executor接口

Spring已经实现的异步线程池(TaskExecutor的实现类):

  1. SimpleAsyncTaskExecutor:不是真的线程池,这个类不重用线程,每次调用都会创建一个新的线程。

  2. SyncTaskExecutor:这个类没有实现异步调用,只是一个同步操作。只适用于不需要多线程的地方

  3. ConcurrentTaskExecutor:Executor的适配类,不推荐使用。如果ThreadPoolTaskExecutor不满足要求时,才用考虑使用这个类

  4. SimpleThreadPoolTaskExecutor:是Quartz的SimpleThreadPool的类。线程池同时被quartz和非quartz使用,才需要使用此类

  5. ThreadPoolTaskExecutor :最常使用,推荐。 其实质是对java.util.concurrent.ThreadPoolExecutor的包装

Spring的异步线程池的使用

  1. @Async将方法标注为异步方法,Spring扫描到后,执行该方法时,会另起新线程去执行,非常简单

  2. 为了让@Async注解能够生效,还需要在Spring Boot的主程序中配置@EnableAsync

@Async所修饰的函数不要定义为static类型,这样异步调用不会生效


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

图解服务器端网络架构

图解服务器端网络架构

[日] 宫田宽士 / 曾薇薇 / 人民邮电出版社 / 2015-4 / 79.00元

本书以图配文,详细说明了服务器端网络架构的基础技术和设计要点。基础设计是服务器端网络架构最重要的一个阶段。本书就立足于基础设计的设计细分项目,详细介绍各细分项目的相关技术和设计要点。全书共分为5章,分别讲述进行物理设计、逻辑设计、安全设计和负载均衡设计、高可用性设计以及管理设计时所必需的技术和设计要点。一起来看看 《图解服务器端网络架构》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具