一、创建线程池常用的几种方式
Executors.newCachedThreadPool()---无界线程池,可自动进行线程回收
Executors.newFixedThreadPool(int nThreads)--- 固定大小的线程池
Executors.newSingleThreadExecutor() ---单个后台线程池
直接自己new
ExecutorService threadPool = new ThreadPoolExecutor( ServiceConfig.coreNumOfEngineThread, ServiceConfig.maxNumOfEngineThread, ALIVE_TIME, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>( ServiceConfig.numOfCachedTaskForEngine)); |
二、看看 ThreadPoolExecutor构造方法的几个参数
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; } |
² corePoolSize :核心线程数量,当线程数<corePoolSize时,会创建新的线程来执行任务
² maximumPoolSize :最大线程数量
² workQueue :保存任务的阻塞队列,当线程数>corePoolSize时,任务会放入阻塞队列
² keepAliveTime :保持存活时间,当线程数大于corePoolSize的空闲线程能保持的最大时间
² handler :拒绝策略
添加任务时执行顺序:
1. 如果当前线程数<corePoolSize, 直接创建新的线程来执行任务
2. 如果当前线程数>corePoolSize,workQueue 未满,将任务放入workQueue中
3. 如果当前线程数>corePoolSize,workQueue 已满,新建线程来执行任务(要确定线程数<maximumPoolSize )
4. 如果当前线程>maximumPoolSize ,workQueue 已满时.执行执行handler的rejectedExecution(拒绝策略)
创建任务使用的优先级:corePoolSize>workQueue >maximumPoolSize >handler
ThreadPoolExecutor默认有四个拒绝策略:
1、ThreadPoolExecutor.AbortPolicy() 直接抛出异常RejectedExecutionException
2、ThreadPoolExecutor.CallerRunsPolicy() 直接调用run方法并且阻塞执行
3、ThreadPoolExecutor.DiscardPolicy() 直接丢弃后来的任务
4、ThreadPoolExecutor.DiscardOldestPolicy() 丢弃在队列中队首的任务
当然可以自己继承RejectedExecutionHandler来写拒绝策略.
使用Executors创建线程池
newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } |
corePoolSize=maximumPoolSize =nThreads
keepAliveTime :为0.
LinkedBlockingQueue为无界队列
好处:线程数量固定,不会存在线程重复初始化
坏处:没有对队列大小进行限制,线程初始化后,再也不能回收线程资源,队列可能会
无限增长~
newCachedThreadPool
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); } |
corePoolSize=0,maximumPoolSize 为无限大
keepAliveTime :为60s
SynchronousQueue:每个插入操作必须等待另一个线程的对应移除操作(就是缓冲区为1的生产者消费者模式)