[本文是我对Java Concurrency In Practice 6.1/6.2的归纳和总结. 转载请注明作者和出处, 如有谬误, 欢迎在评论中指正. ]
为什么需要使用线程池? one-thread-per-request可能带来的问题:
1. 线程的创建和销毁会占用一定的资源. 如果请求频繁而对请求的处理是轻量级的(大多的web请求符合该情形), 创建一个线程处理请求后将其销毁的方式是不划算的.
2. 过多的线程导致线程切换频繁, 用于处理请求的CPU时间反而会减少. 如果当前的线程数已经让CPU处于忙碌状态, 那么增加更多的线程不会改善应用的性能.
3. 过多的线程会导致系统稳定性下降.
综上, 我们需要考虑将创建好的线程组织成线程池, 当请求来临时从池中取出线程处理请求, 处理完毕后将线程归还给线程池, 而不是销毁. 另外我们可以限制线程池中的线程数, 以克服线程过多时性能和稳定性下降的缺陷.
Executor
java的Executor Framework包含多个线程池的实现, 所有线程池都派生自Executor接口. Executor接口只定义了一个方法: execute(Runnable task). Executor接口解耦了任务提交和任务执行. Executor接口是基于生产者消费者模式实现的, 提交任务的线程为生产者, 执行任务的线程为消费者. 使用示例:
class TaskExecutionWebServer {
private static final int NTHREADS = 100;
// 创建线程池
private static final Executor exec
= Executors.newFixedThreadPool(NTHREADS);
public static void main(String[] args) throws IOException {
ServerSocket socket = new ServerSocket(80);
while (true) {
final Socket connection = socket.accept();
Runnable task = new Runnable() {
public void run() {
handleRequest(connection);
}
};
// 将任务提交给线程池执行
exec.execute(task);
}
}
}
ExecutorService和线程池的具体实现
ExecutorService接口继承自Executor, 而预定义的线程池类大多实现了ExecutorService接口.
调用Executors类的静态方法可以获取预定义的线程池:
1. newFixedThreadPool. 调用该方法创建最大线程数固定的线程池.
2. newCachedThreadPool. 调用该方法创建可伸缩式线程池, 当线程池中线程的数量超过程序所需时, 会自动销毁多余的线程; 当线程池中的线程不能需要时再创建新的线程执行提交的任务. 该线程池没有最大线程数的限定.
3. newSingleThreadExecutor. 调用该方法创建仅包含一个线程的线程池, 提交给该线程池执行的任务, 都将在这一单个线程中完成处理.
4. newScheduledThreadPool. 调用该方法创建最大线程数固定且支持延迟和周期性重复执行任务的线程池.
ExecutorService接口提供了一些生命周期管理的方法:
1. 关闭线程池. shutdown()方法在关闭前允许执行以前提交的任务, 包括那些已提交但尚未开始执行的任务. 而shutdownNow()方法阻止尚未开始执行的任务启动并试图停止当前正在执行的任务, 返回从未开始执行的任务的列表. 线程池关闭后将拒绝接受新任务, isShutdown()可用于判断线程池是否已关闭.
2. 当线程池已关闭, 并且所有提交给线程池的任务都已完成时, 线程池转变为终止状态. 调用ExecutorService的awaitTermination方法, 将使得当前线程阻塞, 直到线程池转变为终止状态. 通常在调用shutdown方法后紧接着调用awaitTermination方法. isTerminated()用于检测线程池是否处于终止状态.
使用ExecutorService的例子:
class LifecycleWebServer {
private final ExecutorService exec = ...;
public void start() throws IOException {
ServerSocket socket = new ServerSocket(80);
while (!exec.isShutdown()) {
try {
final Socket conn = socket.accept();
exec.execute(new Runnable() {
public void run() { handleRequest(conn); }
});
} catch (RejectedExecutionException e) {
// 线程池关闭后提交任务将抛出RejectedExecutionException异常
if (!exec.isShutdown())
log("task submission rejected", e);
}
}
}
public void stop() { exec.shutdown(); }
void handleRequest(Socket connection) {
Request req = readRequest(connection);
// 如果是关闭请求, 就关闭线程池, 否则分发该请求
if (isShutdownRequest(req))
stop();
else
dispatchRequest(req);
}
}
Timer和ScheduledThreadPoolExecutor的比较
两者都可以用于延时或周期性重复执行某个任务, 但是Timer存在一些缺陷:
1. Timer基于绝对时间来安排任务的调度, 因此系统时钟的改变会对其产生影响. ScheduledThreadPoolExecutor基于相对时间进行任务的调度.
2. Timer创建单一的线程执行定时任务. 假如Timer对象以10ms的间隔重复执行某个任务, 但是其中的一次执行花去了40ms, 这就意味着少执行了至少4次重复任务. ScheduledThreadPoolExecutor可以使用多个线程执行定时任务.
3. 如果在执行任务的过程中抛出运行时异常, Timer的线程会被终止且没有恢复机制. ScheduledThreadPoolExecutor对这种情形做了适当的处理.
综上, JDK5.0之后, 几乎没有理由继续使用Timer调度定时任务了.
分享到:
相关推荐
XXL-JOB是一个分布式任务调度平台,而"xxl-job-executor-go-master"则表示这个项目是XXL-JOB的Go语言实现版本的源码仓库。这个仓库是针对XXL-JOB执行器的一个Go语言实现,它使得开发者可以利用Go语言来编写调度任务...
`azkaban-executor-server-2.5.0.tar.gz`文件包含了Executor Server的所有必要组件和配置,包括服务器端的Java代码、配置文件、日志记录工具等。安装时,你需要解压这个文件,根据提供的文档配置服务器环境,如设置...
【标题】"go-executor-example-master" 指的可能是一个使用 Go 语言实现的执行器示例项目,其中 "master" 通常表示这是项目的主分支或者最新版本。这个项目可能是为了展示如何在 Go 中编写一个执行器,执行器是一种...
azkaban-executor-2.5.0.tar.gz azkaban-executor-2.5.0.tar.gz azkaban-executor-2.5.0.tar.gz
datax
《PyPI官网下载:pysrim-executor-0.1.0.tar.gz——探索Python库的奥秘》 PyPI(Python Package Index)是Python世界中的一个重要组成部分,它是Python开发者分享和获取开源软件包的中心仓库。PyPI上的每一个资源都...
标签 "go-xxl-executor-" 表示这个项目与 Go 语言版本的 XXL Executor 相关,可能包括了执行器的实现、调度器组件、监控界面以及其他配套工具。 在 `go-xxl-executor-master` 压缩包文件中,我们可以预期找到以下...
Python库executor-7.1.1.tar.gz是一个包含Python开发工具的压缩包,主要用于后端开发。这个库名为"Executor",很可能是一个用于执行异步任务或者管理并发操作的框架。在Python编程中,库(library)是预编写好的代码...
高效率 快捷操作
资源来自pypi官网。 资源全名:Flask_Executor-0.3.1-py3-none-any.whl
xxl-job-executor-sample-springboot-2.2.0.jar 与xxl-job配套的执行器包,用于 Docker-compose搭建xxl-job(并配置Python3环境xxl-job执行器) 中相应的文件
《PyPI官网下载:executor-21.1.tar.gz——深入了解Python执行上下文管理库》 在Python编程中,我们经常需要执行系统命令或者进行异步操作,这就是executor库的作用所在。executor-21.1.tar.gz是这个库的一个版本,...
python库。资源全名:docker-executor-0.1.17.tar.gz
资源分类:Python库 所属语言:Python 资源全名:executor-20.0-py2.py3-none-any.whl 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059
资源分类:Python库 所属语言:Python 资源全名:executor-14.1-py2.py3-none-any.whl 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059
资源分类:Python库 所属语言:Python 资源全名:airflow-ecs-fargate-executor-0.9.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059
标题中的"PyPI 官网下载 | executor-21.0.tar.gz"表明这是一个从Python Package Index(PyPI)上下载的开源软件包,名为"executor",版本为21.0,其压缩格式为tar.gz。PyPI是Python开发者发布和分享自己编写的Python...
**Flask Executor** 是一个基于Python的Web框架——**Flask** 的扩展,它允许你在Flask应用中异步执行任务。...通过使用 **Flask_Executor-0.3.1-py3-none-any.whl** 包,你可以轻松地在你的Flask项目中集成这一功能。