java 线程池
执行流程
1, 创建线程池后, 默认不会创建线程, 等到有任务带来才创建线程, 即一个线程处理一个任务
2, 当线程数量达到核心线程数时, 任务放进队列, 如果放入队列失败, 创建新线程处理任务(此时线程池线程数大于核心线程数)
3, 如果线程数大于最大线程数, 执行拒绝策略处理任务
构造方法
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue); public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory); public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler); public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler);
参数解释
corePoolSize: 核心线程数, 当线程数量达到 corePoolSize 后, 后面的任务将会被放进队列排队
maximumPoolSize: 能创建的最大线程数
keepAliveTime: 当线程数量大于核心线程数量的时候生效, 表示空闲时间, 一旦超过这个时间, 该线程将被销毁
unit: 超时单位, TimeUtil 规定, 有7中静态成员变量
workQueue: 一个阻塞队列, 保存等待执行的任务
ArrayBlockingQueue: 基于数组实现的先进先出队列, 创建时必须指定大小, 当需要处理的任务大于队列的大小时, 拒绝策略生效
LinkedBlockingQueue: 基于链表的先进先出队列, 创建时可选指定大小, 如果不指定默认是 Integer.MAX_VALUE
synchronousQueue: 不保存任务, 直接新建一个线程来执行新来的任务
threadFactory: 线程工场, 用于创建线程
handler: 拒绝策略
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常, 这是默认的方式
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
常用方法
public static ExecutorService newFixedThreadPool(int nThreads): 创建线程池, 参数表示核心线程数, 核心线程数等于最大线程数, 使用 LinkedBlockingQueue 队列
public static ExecutorService newSingleThreadExecutor(): 创建线程池, 核心线程数和最大线程数为 1 , 使用 LinkedBlockingQueue 队列
public static ExecutorService newCachedThreadPool(): 创建线程池, 核心线程数为 0, 最大线程数为 Integer.MAX_VALUE , 使用 SynchronousQueue 队列
execute(): 向线程池提交任务
submit(): 也是向线程池提交任务, 能获取到线程的返回值
shutdown(): 关闭线程池, 停止接收新任务, 等待处理完已经接收的任务后关闭
shutdownNow(): 关闭线程池, 立即关闭, 打断正在处理的任务, 清空队列, 返回未处理的任务
getQueue().size(): 队列中等待的任务数量
getPoolSize(): 线程数量
getCompletedTaskCount(): 已经处理的任务数量
使用 new ThreadPoolExecutor() 创建线程池
class MyThread implements Runnable{ private int index; public MyThread(int index){ this.index = index; } @Override public void run() { System.out.println("处理任务:" + index); } } public class Test1 { public static void main(String[] args){ // 任务队列 ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(5); // 拒绝策略 ThreadPoolExecutor.DiscardPolicy handler = new ThreadPoolExecutor.DiscardPolicy(); // 创建线程池 ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 3, 100, TimeUnit.MICROSECONDS, queue, handler); // 1. 任打印 1-15, 每次打印就是一个任务, 有 15 个任务 // 2. 15 个任务, 每次只能处理 2 个, 因为 corePoolSize 是 2; 所以将会有任务进行排队 for (int i = 0; i < 15; i++){ MyThread myThread = new MyThread(i); // 1. 每个队列只能放 5 个任务, 因为队列指定的数量是 5; 所以会有任务放入不成功, 将会创建新线程 // 2. 最大线程数是 3, 因为 maximumPoolSize 是 3; 所以会有任务将被拒绝 // 3. 这里使用的拒绝策略是: 直接抛弃, 并且不抛出异常 executor.execute(myThread); } // 关闭服务 executor.shutdown(); } }