[第一篇]深入学习线程池之线程池简介及工作原理
2019-07-23 本文已影响0人
秋慕云
一、什么是线程池?
通俗来讲,所谓的线程池就是一个线程的“集合”,在这个“集合”里,线程会被创造、回收,以及重复利用。就像一家餐厅一样,包括店长在内的员工就是线程,而这家餐厅就是“集合”,餐厅可以招聘(创造)、解雇员工(回收‘岗位’资源)、安排员工工作(重复利用)。
二、使用线程池的好处?
第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
第三:提高线程的可管理性。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,
还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。
还是上面的例子,如果一家餐厅只靠一个人来经营,在用餐高峰期的时候是忙不过来的,因为他既要帮客户点餐,又要把客户点好的餐送来,还要在客户吃完餐后收拾餐桌和处理掉盘碗碟筷等等。所以,做好的方式是组建一定的团队,比如,厨师、收银员、服务员等。
三、技术背景
在面向对象编程中,创建和销毁对象是非常费时间的,涉及到对内存资源和其他资源的占用和回收。在Java中,虚拟机将试图跟踪每个对象,以便在对象销毁后可以进行垃圾回收。所以提高服务程序效率的一个手段就是尽可能降低创建和销毁对象的次数,特别是一些非常耗资源的对象创建和销毁。
怎么重复利用已有对象进行服务是"池化资源"技术产生的原因。例如大家所熟悉的数据库连接池。
四、线程池工作原理
创建线程池,我们使用ThreadPoolExecutor,ThreadPoolExecutor构造器核心参数如下:
public ThreadPoolExecutor(int corePoolSize, #核心线程数
int maximumPoolSize,#最大线程数
long keepAliveTime, #达到最大线程数数时候,线程池的工作线程空闲后,保持存活的时间
TimeUnit unit, #keepAliveTime单位
BlockingQueue<Runnable> workQueue,#阻塞队列
RejectedExecutionHandler handler #饱和策略
) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
线程池工作流程图
线程池任务执行流程:
- 当线程池小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。
- 当线程池达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行
- 当workQueue已满,且maximumPoolSize > corePoolSize时,新提交任务会创建新线程执行任务
- 当提交任务数超过maximumPoolSize时,新提交任务由RejectedExecutionHandler处理
- 当线程池中超过corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程
- 当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭
测试代码如下:
final ThreadFactory threadFactory = new ThreadFactoryBuilder()
.setNameFormat("Orders-%d")
.setDaemon(true)
.build();
//线程池100个核心线程,最大200个线程,阻塞队列元素个数为1 饱和策略:直接丢弃
final ThreadPoolExecutor executorService = new ThreadPoolExecutor(100, 200,
10L, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(1), threadFactory,
new ThreadPoolExecutor.DiscardPolicy());
for (int i = 0; i < 120; i++) {
executorService.submit(() -> {
System.out.println("id=" + Thread.currentThread().getId() + ",threadName:" + Thread.currentThread().getName());
});
}
executorService.shutdown();//关闭线程池,阻塞直到所有任务执行完毕
System.out.println("the task is over!");
测试结果如下:
id=11,threadName:Orders-0
id=13,threadName:Orders-2
id=12,threadName:Orders-1
id=14,threadName:Orders-3
id=15,threadName:Orders-4
id=16,threadName:Orders-5
id=17,threadName:Orders-6
id=18,threadName:Orders-7
id=19,threadName:Orders-8
id=20,threadName:Orders-9
id=21,threadName:Orders-10
id=22,threadName:Orders-11
id=23,threadName:Orders-12
id=24,threadName:Orders-13
id=25,threadName:Orders-14
id=26,threadName:Orders-15
id=27,threadName:Orders-16
id=28,threadName:Orders-17
id=29,threadName:Orders-18
id=30,threadName:Orders-19
id=31,threadName:Orders-20
id=32,threadName:Orders-21
id=33,threadName:Orders-22
id=34,threadName:Orders-23
id=35,threadName:Orders-24
id=36,threadName:Orders-25
id=37,threadName:Orders-26
id=38,threadName:Orders-27
id=39,threadName:Orders-28
id=40,threadName:Orders-29
id=41,threadName:Orders-30
id=42,threadName:Orders-31
id=43,threadName:Orders-32
id=44,threadName:Orders-33
id=45,threadName:Orders-34
id=46,threadName:Orders-35
id=47,threadName:Orders-36
id=48,threadName:Orders-37
id=49,threadName:Orders-38
id=50,threadName:Orders-39
id=51,threadName:Orders-40
id=52,threadName:Orders-41
id=53,threadName:Orders-42
id=54,threadName:Orders-43
id=55,threadName:Orders-44
id=56,threadName:Orders-45
id=57,threadName:Orders-46
id=58,threadName:Orders-47
id=59,threadName:Orders-48
id=60,threadName:Orders-49
id=61,threadName:Orders-50
id=62,threadName:Orders-51
id=63,threadName:Orders-52
id=64,threadName:Orders-53
id=65,threadName:Orders-54
id=66,threadName:Orders-55
id=67,threadName:Orders-56
id=68,threadName:Orders-57
id=69,threadName:Orders-58
id=70,threadName:Orders-59
id=71,threadName:Orders-60
id=72,threadName:Orders-61
id=73,threadName:Orders-62
id=74,threadName:Orders-63
id=75,threadName:Orders-64
id=76,threadName:Orders-65
id=77,threadName:Orders-66
id=78,threadName:Orders-67
id=79,threadName:Orders-68
id=80,threadName:Orders-69
id=81,threadName:Orders-70
id=82,threadName:Orders-71
id=83,threadName:Orders-72
id=84,threadName:Orders-73
id=85,threadName:Orders-74
id=86,threadName:Orders-75
id=87,threadName:Orders-76
id=88,threadName:Orders-77
id=89,threadName:Orders-78
id=90,threadName:Orders-79
id=91,threadName:Orders-80
id=92,threadName:Orders-81
id=93,threadName:Orders-82
id=94,threadName:Orders-83
id=95,threadName:Orders-84
id=96,threadName:Orders-85
id=97,threadName:Orders-86
id=98,threadName:Orders-87
id=99,threadName:Orders-88
id=100,threadName:Orders-89
id=101,threadName:Orders-90
id=102,threadName:Orders-91
id=103,threadName:Orders-92
id=104,threadName:Orders-93
id=105,threadName:Orders-94
id=106,threadName:Orders-95
id=107,threadName:Orders-96
id=108,threadName:Orders-97
id=109,threadName:Orders-98
id=110,threadName:Orders-99
id=11,threadName:Orders-0
id=12,threadName:Orders-1
id=111,threadName:Orders-100
id=13,threadName:Orders-2
id=112,threadName:Orders-101
id=14,threadName:Orders-3
id=113,threadName:Orders-102
id=15,threadName:Orders-4
id=114,threadName:Orders-103
id=16,threadName:Orders-5
id=115,threadName:Orders-104
id=17,threadName:Orders-6
id=116,threadName:Orders-105
id=18,threadName:Orders-7
id=117,threadName:Orders-106
id=19,threadName:Orders-8
id=118,threadName:Orders-107
id=20,threadName:Orders-9
id=119,threadName:Orders-108
id=120,threadName:Orders-109
the task is over!