线程池的使用
线程池三大方法
线程池主要是使用了三种方法分别表示创建单个线程、创建固定线程池、创建可伸缩的线程池。
ExecutorService threadPool = Executors.newSingleThreadExecutor(); //单个线程
ExecutorService threadPool = Executors.newFixedThreadPool(5); //创建一个固定线程池的大小
ExecutorService threadPool = Executors.newCachedThreadPool(); //可伸缩的,遇强则强,遇弱则弱
本质都是创建ThreadPoolExecutor
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE, //约为21亿
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
线程池七大参数
根据阿里巴巴java开发手册
因此找到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;
}
手动创建线程池
public class Demo01 {
public static void main(String[] args) {
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
2,
Runtime.getRuntime().availableProcessors(),
3,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy() //如果队列满了,还有线程进来,就不处理,抛出异常
// new ThreadPoolExecutor.CallerRunsPolicy() //哪来的去哪里,一般由main线程执行
// new ThreadPoolExecutor.DiscardPolicy() //队列满了不抛出异常,丢掉任务
// new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了尝试跟最早的竞争,不会抛出异常
);
try {
for (int i = 1; i <= 15; i++) {
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+" ok");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
}
四种拒绝策略
new ThreadPoolExecutor.AbortPolicy() =====>如果队列满了,还有线程进来,就不处理,抛出异常
new ThreadPoolExecutor.CallerRunsPolicy() =====>哪来的去哪里,一般由main线程执行
new ThreadPoolExecutor.DiscardPolicy() =====>队列满了不抛出异常,丢掉任务
new ThreadPoolExecutor.DiscardOldestPolicy() =====>队列满了尝试跟最早的竞争,不会抛出异常
CPU密集型和IO密集型
池的最大大小如何设置
CPU密集型:几核,就是几,可以保证CPU效率最高
Runtime.getRuntime().availableProcessors() 可以获取CPU核数
IO密集型:判断你的程序中十分耗io的线程,最大线程大于这个值