写点什么

线程池的优点及其原理,代码实现线程池。简单、明了。

发布于: 2020 年 12 月 04 日

一 使用线程池的好处


池化技术应用:线程池、数据库连接池、http 连接池等等。


池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率。


线程池提供了一种限制、管理资源的策略。 每个线程池还维护一些基本统计信息,例如已完成任务的数量。


使用线程池的好处:


  • 降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁造成的消耗。

  • 提高响应速度:当任务到达时,可以不需要等待线程创建就能立即执行。

  • 提高线程的可管理性:线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,监控和调优。


二 Executor 框架


Executor 框架不仅包括了线程池的管理,还提供了线程工厂、队列以及拒绝策略等,让并发编程变得更加简单。


Executor 框架的使用示意图



  1. 主线程首先要创建实现 Runnable 或 Callable 接口的任务对象。

  2. 把创建完成的实现 Runnable/Callable 接口的对象直接交给 ExecutorService 执行:


ExecutorService.execute(Runnable command)或者ExecutorService.sumbit(Runnable command)或ExecutorService.sumbit(Callable <T> task).
复制代码


  1. 如果执行 ExecutorService.submit(...),ExecutorService 将返回一个实现 Future 接口的对象。最后,主线程可以执行 FutureTask.get()方法来等待任务执行完成。主线程也可以执行 FutureTask.cancel()来取消次任务的执行。


import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;
public class ThreadPoolExecutorDemo {
private static final int CORE_POOL_SIZE = 5; private static final int MAX_POOL_SIZE = 10; private static final int QUEUE_CAPACITY = 100; private static final Long KEEP_ALIVE_TIME = 1L;
public static void main(String[] args) { ThreadPoolExecutor executor = new ThreadPoolExecutor( CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, new ArrayBlockingQueue<>(QUEUE_CAPACITY), new ThreadPoolExecutor.CallerRunsPolicy());
//执行线程代码
executor.shutdown();
}
}
复制代码


CORE_POOL_SIZE:核心线程数定义了最小可以同时运行的线程数量。


MAX_POOL_SIZE:当队列中存放的任务到达队列容量的时候,当前可以同时运行的线程数量变为最大线程数。


QUEUE_CAPACITY:当新任务加入是会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,任务就会被存放到队列中。


KEEP_ALIVE_TIME:当线程池中的线程数量大于核心线程数时,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过 KEEP_ALIVE_TIME 才会被回收销毁。


ThreadPoolExecutor.CallerRunsPolicy():调用执行自己的线程运行任务,也就是直接在调用 execute 方法的线程运行(run)被拒绝的任务,如果执行程序已关闭,则会丢弃任务。因此这种策略会降低新任务的提交速度,影响程序的整体性能。另外,这个策略喜欢增加队列容量。如果应用程序可以承受此延迟并且不能任务丢弃一个任务请求的话,可以选择这个策略。


线程池分析原理



三 线程池大小确定


有一个简单且使用面比较广的公式:


  • CPU 密集型任务(N+1):这种任务消耗的主要是 CPU 资源,可以将线程数设置为 N(CPU 核心数)+1,比 CPU 核心数多出来一个线程是为了防止线程偶发的缺页中断,或者其他原因导致的任务暂停而带来的影响。一旦任务停止,CPU 就会处于空闲状态,而这种情况下多出来一个线程就可以充分利用 CPU 的空闲时间。

  • I/O 密集型(2N):这种任务应用起来,系统大部分时间用来处理 I/O 交互,而线程在处理 I/O 的是时间段内不会占用 CPU 来处理,这时就可以将 CPU 交出给其他线程使用。因此在 I/O 密集型任务的应用中,可以配置多一些线程,具体计算方是 2N。


四 代码实现线程池


如果还有不懂的朋友可以看看这个 150 行代码小时一个线程池的视频讲解,点击:「链接」


需要视频代码的朋友可以加 qun720209036


看完的都是真爱,点个赞再走呗?您的「三连」就是我的最大动力!


  1. 关注公众号「Linux C 后台服务器开发」,第一时间获取最新 Linux 干货!

  2. 加群 720209036 获取精选一线大厂面试、自我提升、简历等资料。



用户头像

Linux服务器开发qun720209036,欢迎来交流 2020.11.26 加入

专注C/C++ Linux后台服务器开发。

评论

发布
暂无评论
线程池的优点及其原理,代码实现线程池。简单、明了。