标签:unless uri 操作 pre 取出 大小 pool lex 最大值
线程池:三大方法、七大参数、4种拒绝策略
1、降低资源的消耗
2、提高响应速度
3、方便管理
线程复用、可以控制最大并发数、管理线程
ExecutorService threadPool = Executors.newSingleThreadExecutor(); //创建只有单个线程的线程池
ExecutorService threadPool = Executors.newFixedThreadPool(5); //创建固定大小为5的线程池
ExecutorService threadPool = Executors.newCachedThreadPool(); //创建一个可伸缩的线程池
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1, //核心数和最大数都为1
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>())); //阻塞队列的最大值为Integer.MAX_VALUE 这样会导致OOM,见阿里巴巴java开发者手册
}
//阻塞队列代码
public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);
}
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(nThreads, nThreads, //核心数和最大数都是传入的大小
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(), ////阻塞队列的最大值为Integer.MAX_VALUE 这样会导致OOM,见阿里巴巴java开发者手册
threadFactory);
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE, //核心数为0,最大值约为21亿 (会导致OOM ,见阿里巴巴java开发者手册)
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
观察上面的三种方法,发现其本质都是使用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.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
注意:上面介绍三种方法时,说明了会产生OOM,所以必须要使用ThreadPoolExecutor来创建线程池
线程池有三个重要的参数 核心线程数 最大线程数 阻塞队列,线程池触发拒绝策略需要这三个参数总体协调,而不是简单超过了最大线程数就触发。
当提交的任务数大于corePoolSize(核心线程数)时,会优先放入到阻塞队列中,只有填满了阻塞队列后,才会判断当前运行的任务是否大于maxPoolSize(线程最大数),小于时会新建线程进行处理。大于时就会触发拒绝策略。总结就是 当提交的任务数 大于 (maxPoolSize + queueCapacity(阻塞队列)) 时就会触发线程池的拒绝策略
public static class AbortPolicy implements RejectedExecutionHandler {
/**
* Creates an {@code AbortPolicy}.
*/
public AbortPolicy() { }
/**
* Always throws RejectedExecutionException.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
* @throws RejectedExecutionException always
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
public static class CallerRunsPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code CallerRunsPolicy}.
*/
public CallerRunsPolicy() { }
/**
* Executes task r in the caller‘s thread, unless the executor
* has been shut down, in which case the task is discarded.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
}
public static class DiscardPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardPolicy}.
*/
public DiscardPolicy() { }
/**
* Does nothing, which has the effect of discarding task r.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardOldestPolicy} for the given executor.
*/
public DiscardOldestPolicy() { }
/**
* Obtains and ignores the next task that the executor
* would otherwise execute, if one is immediately available,
* and then retries execution of task r, unless the executor
* is shut down, in which case task r is instead discarded.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
标签:unless uri 操作 pre 取出 大小 pool lex 最大值
原文地址:https://www.cnblogs.com/liuzhidao/p/14243667.html