JAVA线程池_并发队列工作笔记0002---认识线程池_在线程池中使用队列_JAVA零碎要点

上面是线程的执行周期

JAVA线程池_并发队列工作笔记0002---认识线程池_在线程池中使用队列_JAVA零碎要点_02

这个线程的生命周期,可以看到时间都浪费在了创建和销毁的这里了.

实际上执行业务的时间只有1s

JAVA线程池_并发队列工作笔记0002---认识线程池_在线程池中使用队列_JAVA零碎要点_03

在高并发的时候,如果持续的去,创建,销毁,那么是很浪费时间的

这个时候就需要用线程池

JAVA线程池_并发队列工作笔记0002---认识线程池_在线程池中使用队列_JAVA零碎要点_04

用了线程池以后,线程的创建用的3秒,销毁用的2秒就没有了,

只剩运行时间用的1s了.

比如有100个任务要执行,那么我们的线程池是10个线程,

那么也就是说,线程池已经准备好10个线程去用了,

这10个线程同时去执行10个任务,那么剩余的90个任务,因为咱们用的是阻塞队列

所以剩余的90个任务就会阻塞等待执行.

JAVA线程池_并发队列工作笔记0002---认识线程池_在线程池中使用队列_JAVA零碎要点_05

可以看一下这个线程队列的工作过程,

首先,这里

ThreadPoolExecutor t=new ThreadPoolExecutor(1,3,0,TimeUnit.MILISECONDS,new LinkedBlockingDeque<Runnable>(3));

这里1,是核心线程数,就是在线程池中活动的线程数,然后3是最大线程数,也就是可以开启的最大线程数,

然后0是超时时间,后面是这个超时时间的单位,这个超时时间的意思是,除了核心线程,我另外创建的线程,如果没有任务添加进来的话,那么线程需要等多久

被销毁掉,然后后面的new LinkedBlockingDeque<Runnable>(3)是一个阻塞队列.

3是队列的大小,这里如果队列的大小,不填写的话,那么,默认就是Integer.MAX_VALUE这个数

2147483647 21亿多

JAVA线程池_并发队列工作笔记0002---认识线程池_在线程池中使用队列_JAVA零碎要点_05

然后再看一下这个线程池队列的工作过程:

比如一个任务来了,因为一个任务就等于一个线程,那么就要先判断,是否现在正在工作的线程个数,大于核心线程数(已经创建好的可以用的线程数)了,

如果没有大于核心线程数,那么就从就绪的线程中拿一个,去执行任务就可以了,如果大于了核心线程数,那么,再去判断,

任务放在队列中,这个队列的大小满了没,比如说3个,队列中的任务大于3个了嘛,没有大于3个,就把这个任务继续放到这个

队列中去,然后等待,正在执行的线程,用完了以后空闲下来,再去执行队列里面的任务,如果

任务往队列中放的时候,发现队列已经满了,那么这个时候,就可以创建新线程来执行任务,这个时候再做个判断,

如果创建的新线程数量+核心线程数量<=最大线程数的时候,那么就利用新创建的线程和核心线程来分摊任务,

如果新线程数量+核心线程数量>最大线程数量的话,那么,这个时候程序就会报错,这个在实际应用中我们发生过,

就会拒绝这个任务的加入.

 

这个超时时间的意思是,当队列中的任务已经满了,并且核心线程也都在用着,那么我去创建新线程,

那么,我创建的这个新的线程,执行完这个队列中溢出的任务以后,这个线程不会立刻销毁,我们这个线程

需要等等看,还有没有新线程,如果有的话我就继续执行去,如果没有我就等等,等多久销毁,这里是指定的这个时间.

 

接下来用代码,弄一下上面的过程:

JAVA线程池_并发队列工作笔记0002---认识线程池_在线程池中使用队列_JAVA零碎要点_07

这里创建一个线程池,指定,核心线程数1,最大线程数2,新创建线程超时时间3,秒,然后用阻塞队列,队列大小是3

JAVA线程池_并发队列工作笔记0002---认识线程池_在线程池中使用队列_JAVA零碎要点_08

这里我执行一个任务,注意用完线程池,要关闭

JAVA线程池_并发队列工作笔记0002---认识线程池_在线程池中使用队列_JAVA零碎要点_09

这个时候核心线程,在执行这个任务,然后

这个时候队列中是空的,因为一个线程已经从队列中取出,正在执行

那么我又放了3个任务,这个时候,队列正好是满的了

JAVA线程池_并发队列工作笔记0002---认识线程池_在线程池中使用队列_JAVA零碎要点_10

可以看到这里,打印出了4个,都是用第一个线程执行的.

因为第一个线程正在执行第一个任务,然后第2,3,4个任务正好在队列中,

队列还能容得下,所以也没有创建新线程.

JAVA线程池_并发队列工作笔记0002---认识线程池_在线程池中使用队列_JAVA零碎要点_11

然后如果我再添加一个任务,那么就是,

第一个核心线程正在执行第一个任务,然后第2,3,4个任务在队列中,然后如果这个时候,再来一个任务

第5个任务,这个时候队列中也不能放了,这个时候,就会

再创建一个新线程来执行,咱们看看

JAVA线程池_并发队列工作笔记0002---认识线程池_在线程池中使用队列_JAVA零碎要点_12

可以看到第5个任务是用thread2来执行的.

JAVA线程池_并发队列工作笔记0002---认识线程池_在线程池中使用队列_JAVA零碎要点_13

然后再执行可以看到,有几个任务是用thread2来执行的,这个就是说,咱们上面说的

核心线程会和新创建的线程分摊这任务,所以只要是谁有时间谁就去执行这个任务.

JAVA线程池_并发队列工作笔记0002---认识线程池_在线程池中使用队列_JAVA零碎要点_14

那么如果,咱们再去添加任务呢?

可以看到,第一个核心线程去执行第一个任务

然后,第2,3,4个任务放在容量为3个阻塞队列里,然后

第5个任务来的时候,阻塞队列容量不够了会新创建一个线程去执行,

然后第6个任务来的时候,因为咱们最大线程数设置的是2,现在已经是2个线程了,所以这个时候

就会拒绝服务,报错了.

 

这个就是线程池的应用.