线程池优点
- 限流
控制线程总数,根据硬件人为控制使性能达到最优 - 复用
减少线程的频繁创建和销毁复用线程 - 效率
因为线程可复用任务相应更快
java中的线程池
Executors.newFixedThreadPool(nThreads);//固定线程数线程池
Executors.newCachedThreadPool();//有伸缩性线程池,线程60shou后回收
Executors.newSingleThreadExecutor();//只有一个核心线程的线程池
Executors.newSingleThreadScheduledExecutor();//定时任务线程池
Executors.newWorkStealingPool();//fork/join线程池
- Executors核心构造方法
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;
}
- newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, //核心线程数=传入线程数
nThreads,//最大线程数=传入线程数
0L,//超时间=0
TimeUnit.MILLISECONDS,//超时时间单位=秒
new LinkedBlockingQueue<Runnable>()//双向链表阻塞队列
);
}
- newCachedThreadPool
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(
0, //核心线程数=0
Integer.MAX_VALUE,//最大线程数=Integer最大值(可当做无限大)
60L, //超时时间=60
TimeUnit.SECONDS,//超时时间单位=秒
new SynchronousQueue<Runnable>()//不存储元素的阻塞队列
);
}
- newSingleThreadExecutor
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 核心线程数=1
1,//最大线程数=1
0L,//超时时间0
TimeUnit.MILLISECONDS,//超时时间单位:毫秒
new LinkedBlockingQueue<Runnable>()//双向链表阻塞队列
));
}
执行流程图
image.png
问题
- 1.不建议使用Executors创建线程池?为什么?
Executors创建的线程池内置的参数,使开发人员在不用了解线程池各个参数的含义的情况下进行使用.
在实际生产环境上运行是十分危险的 - 2.线程池大小的设置?
CPU 核数:
IO密集型:每个线程执行时间长,cpu利用率低;可以多设置一些;CPU核数2或者 (线程等待时间+线程CUP时间)/线程CPU时间cup核数
CUP密集型:cpu核数+1
-3.线程池预热:
ThreadPollExecutor.prestartAllCoreThreads()
- 4
execute()与 submit()
的区别
submit(Callable<T>)
执行待返回值的任务,根据返回值可知任务的执行结果
submit()
不会抛出异常,异常根据Callable返回