线程池原理
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; }
corePoolSize 核心线程数;
maximumPoolSize 最大线程数;
keepAliveTime 空闲线程数存活时间;
TimeUnit 时间格式;
BlockingQueue 工作阻塞队列;
threadFactory 线程工厂;
RejectedExecutionHandler 拒绝策略。
我们知道java中Executors提供了三种创建线程池的方法:
//默认单个线程 ExecutorService executorService =Executors.newSingleThreadExecutor(); //指定线程数 ExecutorService executorService2 =Executors.newFixedThreadPool(3); //带缓存可扩容数最大Integer.MAX_VALUE ExecutorService executorService3 =Executors.newCachedThreadPool();
前两者使用的阻塞队列为LinkedBlockingQueue,链表阻塞队列,虽然是有界队列,
但是它最大值为Integer.MAX_VALUE,21亿左右,容易产生OOM问题;所以需要
使用线程池时,需要我们自己手写线程池,并配上对应七大参数;
其中最大核心数要根据服务环境的cpu数来配置:
Runtime.getRuntime().availableProcessors();//获取可用cpu核心数
cpu密集型:core + 1
io密集型: core / (1 - 阻塞系数)或者core * 2 //阻塞系数(0.8-0.9)
RejectedExecutionHandler 默认采用
private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();
在超过最大核心数和阻塞队列最大值时会抛出异常,所以不要采用默认拒绝策略。