线程池之线程池说明
一,线程池
我们知道线程不可能无限制的创建,但是现实需求中遇到并发请求多任务的时候,会用多线程来处理,但是这么多的线程又不可能全部创建出来,这时我们就会想到线程池了,
说道线程池,它其实就是一种管理多线程一种手段。下面的代码是描述要测试的使用的代码,
package com.test.thread; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.junit.Test; public class TestThreadPool { /** * 一个阻塞队列 */ BlockingQueue<Runnable> queues=new LinkedBlockingQueue<Runnable>(10); /** * 线程池 初始化10个线程 最大线程数量为20个,空闲时间为0L秒 */ ThreadPoolExecutor pool= new ThreadPoolExecutor(10, 20,0L,TimeUnit.MICROSECONDS,queues); /** * * @param threadNum 执行线程数量 * @throws InterruptedException */ private void testThreadPool(int threadNum)throws InterruptedException{ for(int i=1;i<=threadNum;i++){ pool.execute(new Task("aa@"+i)); } //停顿一秒钟等待线程池中初始化线程都启动 Thread.sleep(1000); //打印当前阻塞队列中有多少线程 System.out.println("此时阻塞队列有多个少任务:"+"数量->"+queues.size()+",具体线程->"+queues); System.out.println("线程池中执行的线程:"+pool.getActiveCount()); /** * shutdown方法的时候,线程池不再接收任何新任务,但此时线程池并不会立刻退出,直到添加到线程池中的任务都已经处理完成,才会退出。 * 在调用shutdown方法后我们可以在一个死循环里面用isTerminated方法判断是否线程池中的所有线程已经执行完毕,如果子线程都结束了,我们就可以做关闭流等后续操作了。 */ pool.shutdown(); while(true){ if(pool.isTerminated()){ System.out.println("所有任务执行完成....."); break; } Thread.sleep(200); } } /** * 测试5个线程 * @throws InterruptedException */ @Test public void testThreadPool5() throws InterruptedException { testThreadPool(5); } /** * 测试15个线程 * @throws InterruptedException */ @Test public void testThreadPool15() throws InterruptedException{ testThreadPool(15); } /** * 测试25个线程 * @throws InterruptedException */ @Test public void testThreadPool25() throws InterruptedException{ testThreadPool(25); } /** * 测试45个线程 * @throws InterruptedException */ @Test public void testThreadPool45() throws InterruptedException{ testThreadPool(45); } } class Task implements Runnable{ String name; public Task(String name) { this.name=name; } @Override public void run() { System.out.println("线程["+name+"]启动... 开始执行任务"); try { Thread.sleep(30000L); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("线程["+name+"]结束--- 完成任务"); } @Override public String toString() { return name; } }
(1)当 执行testThreadPool5()方法时候 ,这里 线程为5个数量
其中打印结果
线程[aa@2]启动... 开始执行任务 线程[aa@1]启动... 开始执行任务 线程[aa@4]启动... 开始执行任务 线程[aa@3]启动... 开始执行任务 线程[aa@5]启动... 开始执行任务 此时阻塞队列有多个少任务:数量->0,具体线程->[] 线程池中执行的线程:5 线程[aa@1]结束--- 完成任务 线程[aa@5]结束--- 完成任务 线程[aa@3]结束--- 完成任务 线程[aa@4]结束--- 完成任务 线程[aa@2]结束--- 完成任务 所有任务执行完成.....
从打印结果中我们可以看到 由于 给定的执行线程数量5 小于初始化数量10 所以 不会多余的线程放入阻塞队列中
(2)当执行testThreadPool15() 方法,这里给定执行的线程为15
其中打印结果
线程[aa@1]启动... 开始执行任务 线程[aa@3]启动... 开始执行任务 线程[aa@2]启动... 开始执行任务 线程[aa@4]启动... 开始执行任务 线程[aa@5]启动... 开始执行任务 线程[aa@6]启动... 开始执行任务 线程[aa@7]启动... 开始执行任务 线程[aa@9]启动... 开始执行任务 线程[aa@8]启动... 开始执行任务 线程[aa@10]启动... 开始执行任务 此时阻塞队列有多个少任务:数量->5,具体线程->[aa@11, aa@12, aa@13, aa@14, aa@15] 线程池中执行的线程:10 线程[aa@2]结束--- 完成任务 线程[aa@1]结束--- 完成任务 线程[aa@3]结束--- 完成任务 线程[aa@11]启动... 开始执行任务 线程[aa@6]结束--- 完成任务 线程[aa@5]结束--- 完成任务 线程[aa@15]启动... 开始执行任务 线程[aa@4]结束--- 完成任务 线程[aa@12]启动... 开始执行任务 线程[aa@13]启动... 开始执行任务 线程[aa@14]启动... 开始执行任务 线程[aa@10]结束--- 完成任务 线程[aa@7]结束--- 完成任务 线程[aa@9]结束--- 完成任务 线程[aa@8]结束--- 完成任务 线程[aa@11]结束--- 完成任务 线程[aa@15]结束--- 完成任务 线程[aa@12]结束--- 完成任务 线程[aa@13]结束--- 完成任务 线程[aa@14]结束--- 完成任务 所有任务执行完成.....
从打印结果中我们可以看到 由于 给定的执行线程数量15 大于初始化数量10 小于最大线程数量20,所以 多余的线程放入阻塞队列中为5个 随着前十个线程逐渐执行完成时, 阻塞队列中的线程也开始加入执行中,最终队列全部完成
(3)当执行testThreadPool25() 方法,这里给定执行的线程为25
其中打印结果
线程[aa@1]启动... 开始执行任务 线程[aa@4]启动... 开始执行任务 线程[aa@3]启动... 开始执行任务 线程[aa@5]启动... 开始执行任务 线程[aa@6]启动... 开始执行任务 线程[aa@2]启动... 开始执行任务 线程[aa@7]启动... 开始执行任务 线程[aa@8]启动... 开始执行任务 线程[aa@9]启动... 开始执行任务 线程[aa@10]启动... 开始执行任务 线程[aa@21]启动... 开始执行任务 线程[aa@23]启动... 开始执行任务 线程[aa@22]启动... 开始执行任务 线程[aa@24]启动... 开始执行任务 线程[aa@25]启动... 开始执行任务 此时阻塞队列有多个少任务:数量->10,具体线程->[aa@11, aa@12, aa@13, aa@14, aa@15, aa@16, aa@17, aa@18, aa@19, aa@20] 线程池中执行的线程:15 线程[aa@10]结束--- 完成任务 线程[aa@2]结束--- 完成任务 线程[aa@7]结束--- 完成任务 线程[aa@5]结束--- 完成任务 线程[aa@8]结束--- 完成任务 线程[aa@4]结束--- 完成任务 线程[aa@9]结束--- 完成任务 线程[aa@16]启动... 开始执行任务 线程[aa@1]结束--- 完成任务 线程[aa@14]启动... 开始执行任务 线程[aa@15]启动... 开始执行任务 线程[aa@13]启动... 开始执行任务 线程[aa@3]结束--- 完成任务 线程[aa@19]启动... 开始执行任务 线程[aa@12]启动... 开始执行任务 线程[aa@11]启动... 开始执行任务 线程[aa@6]结束--- 完成任务 线程[aa@20]启动... 开始执行任务 线程[aa@18]启动... 开始执行任务 线程[aa@17]启动... 开始执行任务 线程[aa@23]结束--- 完成任务 线程[aa@21]结束--- 完成任务 线程[aa@22]结束--- 完成任务 线程[aa@24]结束--- 完成任务 线程[aa@25]结束--- 完成任务 线程[aa@16]结束--- 完成任务 线程[aa@17]结束--- 完成任务 线程[aa@18]结束--- 完成任务 线程[aa@20]结束--- 完成任务 线程[aa@11]结束--- 完成任务 线程[aa@12]结束--- 完成任务 线程[aa@19]结束--- 完成任务 线程[aa@13]结束--- 完成任务 线程[aa@15]结束--- 完成任务 线程[aa@14]结束--- 完成任务 所有任务执行完成.....
从打印结果中我们可以看到 由于 给定的执行线程数量25 大于初始化数量10 大于最大线程数量20,所以 多余的线程放入阻塞队列中为10个 这是线程池中就有15个线程在执行 (这个数量小于最大数量限制20)
(3)当执行testThreadPool45() 方法,这里给定执行的线程为45
这时打印结果会报错 如下图
由于 给定的执行线程数量25 大于初始化数量10 大于最大线程数量20,而阻塞队列最多可以放置10个 这是线程池中就有25个线程执行 但是由于线程池最大数量是20 不能同时执行25个所以报错
综上所述 假设 执行线程数量 threadNum,初始化线程数量 corePoolSize, 线程最大允许执行数量maximumPoolSize ,阻塞队列容量queueNums
1,当threadNum<corePoolSize 时候直接执行,阻塞队列没有多余线程可放
2,当corePoolSize<threadNum<maximumPoolSize ,阻塞队列线程数量min(queueNums,threadNum-corePoolSize) 执行的线程数量为corePoolSize
3,当threadNum>maximumPoolSize且 (threadNum-min(queueNums,threadNum-corePoolSize))<maximumPoolSize 阻塞队列线程数量min(queueNums,threadNum-corePoolSize) 执行的线程数量为threadNum-min(queueNums,threadNum-corePoolSize)
4,当 3,当threadNum>maximumPoolSize且 (threadNum-min(queueNums,threadNum-corePoolSize))>maximumPoolSize 直接报错 抛异常
下一篇: 线程池