From 0b6b091e84e1bc276366ed2db2a22385a91b7a95 Mon Sep 17 00:00:00 2001 From: Omooo <869759698@qq.com> Date: Mon, 15 Jun 2020 18:01:27 +0800 Subject: [PATCH] =?UTF-8?q?Create=20=E7=BA=BF=E7=A8=8B=E6=B1=A0.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blogs/Java/口水话/线程池.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 blogs/Java/口水话/线程池.md diff --git a/blogs/Java/口水话/线程池.md b/blogs/Java/口水话/线程池.md new file mode 100644 index 0000000..7552634 --- /dev/null +++ b/blogs/Java/口水话/线程池.md @@ -0,0 +1,16 @@ +--- +线程池口水话 +--- + +#### 目录 + +1. 线程池存在的意义 +2. 源码哔哔 + +#### 线程池存在的意义 + +线程池存在的意义是降低资源消耗,通过重复利用已创建的线程降低线程创建和销毁造成的消耗,同时能够提高响应速度,当任务到达时,任务可以不需要等到线程创建就能够立即执行,起到缓存线程的效果。这种缓存对象实例的池化思想在 Android 中也有应用,比如 Handler 中使用到的 Message 消息池。 + +在 Java 中的线程池是用 ThreadPoolExecutor 类来实现的,它的构造方法中有一系列参数需要指定。首先是 corePoolSize 核心线程数量,当有任务通过 execute 方法提交时,如果当前运行的线程数 workCount 小于核心线程数,就新建一个线程去执行任务,如果 workCount 大于等于核心线程数并且队列未满时就扔进队列里面,等待有空闲的线程自己去从队列里面去取然后执行;如果此时队列满了,但是未达到最大线程数,就新建一个线程去执行任务,如果已经达到了最大线程数并且队列满了,就执行拒绝策略。第二个参数就是指定最大线程数,第三个参数是阻塞队列,在任务提交时,如果线程池中的线程数量大于等于 corePoolSize 时,就会把该任务封装成一个 Worker 对象放入等待队列里。在使用 Executors 的 newFixedThreadPool 或 newSingleThreadPool 创建线程池时使用的是 LinkedBlockingQueue,而在使用 newCachedThreadPool 使用的是 SynchronousQueue。但是通常不建议直接使用 Executors 创建线程池,因为 LinkedBlockingQueue 默认大小是 Integer.MAX_VALUE,可能会撑爆内存。第四个参数 keepAliveTime 是非核心线程的存活时间,第五个参数 threadFactory 是用来创建新线程的,默认是 DefaultThreadFactory,在 newThread 里面会设置线程的 group、优先级、是否是守护线程以及线程名称。最后一个参数是拒绝策略,默认是 AbortPolicy 直接抛异常。其次还有其他三个,这四个都定义在了 ThreadPoolExecutor 的内部类中,ThreadPoolExecutor 一共有五个内部类,还有一个就是上面讲到的 Worker。 + +然后再说说 ThreadPoolExecutor 的一个比较重要的字段,即原子类 ctl,它的高三位表示 runState 运行状态,后二十九位表示 workCount。线程池一共有五种运行状态,RUNNING 状态就是能够接受新提交的任务,并且也能处理阻塞队列中的任务;SHUTDOWN 关闭状态,就是不在接受新提交的任务,但却可以继续处理阻塞队列中已保存的任务,当调用 shutdown 方法会使线程池进入到该状态;STOP 状态不能接受新任务,也不处理队列中的任务,会尝试中断正在处理任务的线程,当调用 shutdownNow 时进行该状态;TIDYING 状态是所有任务已经终止了,workCount 为零。线程池进入该状态后就会调用 terminated 方法进入 TERMINATED 状态。 \ No newline at end of file