自定义线程池
如果当前线程池中的线程数目小于corePoolSize,则每来一个任务,就会创建一个线程去执行这个任务;
如果当前线程池中的线程数目>=corePoolSize,则每来一个任务,会尝试将其添加到任务缓存队列当中,若添加成功,则该任务会等待空闲线程将其取出去执行;若添加失败(一般来说是任务缓存队列已满),则会尝试创建新的线程去执行这个任务;
如果队列已经满了,则在总线程数不大于maximumPoolSize的前提下,则创建新的线程
如果当前线程池中的线程数目达到maximumPoolSize,则会采取任务拒绝策略进行处理;
如果线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止,直至线程池中的线程数目不大于corePoolSize;如果允许为核心池中的线程设置存活时间,那么核心池中的线程空闲时间超过keepAliveTime,线程也会被终止。
废话不多说,上手撸代码!
先把这个代码copy到你的main函数,毕竟都是这个封装的,咱们也封装封装玩玩~
new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
然后封装到这个样子:
package com.toov5.ThreadPoolTest; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; class TaskThread implements Runnable{ private String threadName; public TaskThread(String thradName) { this.threadName=thradName; } @Override public void run() { System.out.println(threadName); } } public class DefinedThreadPool { public static void main(String[] args) { //核心线程数1 最大线程数2 1是实际运行的线程数 2是最多可以创建的线程数 后面的表示存活的时间(如果线程有空闲 超时时间 节约内存回收掉) //这里是0L 用完就杀死了 不回收了 最好设置超时时间 配置30s 有时候配置太长线程不能立马被复用到 太短容易产生超时 //单位是毫秒 //队列的初始化值是3 ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(3)); //任务1现在创建线程 执行 threadPoolExecutor.execute(new TaskThread("任务1")); //两个任务 任务2大于1 此时的队列大小是(3)没有满 那么任务2进入队列 threadPoolExecutor.execute(new TaskThread("任务2")); threadPoolExecutor.execute(new TaskThread("任务3")); } }
任务 2 任务3 此时放到队列去了
结果:
下面搞坏他!哈哈哈
package com.toov5.ThreadPoolTest; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; class TaskThread implements Runnable{ private String threadName; public TaskThread(String thradName) { this.threadName=thradName; } @Override public void run() { System.out.println(threadName); } } public class DefinedThreadPool { public static void main(String[] args) { //核心线程数1 最大线程数2 1是实际运行的线程数 2是最多可以创建的线程数 后面的表示存活的时间(如果线程有空闲 超时时间 节约内存回收掉) //这里是0L 用完就杀死了 不回收了 最好设置超时时间 配置30s 有时候配置太长线程不能立马被复用到 太短容易产生超时 //单位是毫秒 //队列的初始化值是3 ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(3)); //任务1现在创建线程 执行 threadPoolExecutor.execute(new TaskThread("任务1")); //两个任务 任务2大于1 此时的队列大小是(3)没有满 那么任务2进入队列 threadPoolExecutor.execute(new TaskThread("任务2")); threadPoolExecutor.execute(new TaskThread("任务3")); threadPoolExecutor.execute(new TaskThread("任务4")); threadPoolExecutor.execute(new TaskThread("任务5")); threadPoolExecutor.execute(new TaskThread("任务6")); } }
看吧:
报错了!
分析下:
package com.toov5.ThreadPoolTest; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; class TaskThread implements Runnable{ private String threadName; public TaskThread(String thradName) { this.threadName=thradName; } @Override public void run() { System.out.println(Thread.currentThread().getName()+threadName); } } public class DefinedThreadPool { public static void main(String[] args) { //核心线程数1 最大线程数2 1是实际运行的线程数 2是最多可以创建的线程数 后面的表示存活的时间(如果线程有空闲 超时时间 节约内存回收掉) //这里是0L 用完就杀死了 不回收了 最好设置超时时间 配置30s 有时候配置太长线程不能立马被复用到 太短容易产生超时 //单位是毫秒 //队列的初始化值是3 ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(3)); //任务1现在创建线程 执行 threadPoolExecutor.execute(new TaskThread("任务1")); //两个任务 任务2大于1 此时的队列大小是(3)没有满 那么任务2进入队列 threadPoolExecutor.execute(new TaskThread("任务2")); threadPoolExecutor.execute(new TaskThread("任务3")); threadPoolExecutor.execute(new TaskThread("任务4")); threadPoolExecutor.execute(new TaskThread("任务5")); // threadPoolExecutor.execute(new TaskThread("任务6")); } }
线程就两个 1和2 来回复用 线程池就一个
最大线程数+队列缓存数 一旦超过就报错
大家可以自己玩玩体验一把,如果我执行的是1-5的任务 那么都是线程1 2 来复用
但是如果超过了 队列数+核心线程数 那么就要创新信的线程了,大家可以试试玩玩
核心线程数 是实际运行的线程数
最大线程数 是可以创建的线程数 大于等于最大线程数那么会 拒绝任务了
如果超出了队列数量并且没有超出最大线程数 则创建新的线程 并且也会加入复用的行列
保证所有真正线程都能 被实际用到 核心线程数 实际运行的线程
最大线程数 最多可以创建多少个线程
大家可以这么理解