线程池: 3大方法、4种拒绝策略、7大参数
池化技术: 事先准备好一些资源,有人要用,就来我这里拿,用完之后还给我。
线程池的好处:
1、降低资源的消耗
2、提高响应的速度
3、方便管理。
线程复用、可以控制最大并发数、管理线程
阿里巴巴java开发手册明确指出:
【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
说明: Executors 返回的线程池对象的弊端如下:
1) FixedThreadPool 和 SingleThreadPool :
允许的请求队列长度为 Integer.MAX_VALUE ,可能会堆积大量的请求,从而导致 OOM 。
2) CachedThreadPool 和 ScheduledThreadPool :
允许的创建线程数量为 Integer.MAX_VALUE ,可能会创建大量的线程,从而导致 OOM 。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class test1{
public static void main(String[] args) {
// 创建线程池的3种方法,以下3种方式创建的线程池底层都是使用ThreadPoolExecutor(...)来创建线程!
ExecutorService executorService1 = Executors.newSingleThreadExecutor();
//ExecutorService executorService2 = Executors.newFixedThreadPool(5);
//ExecutorService executorService3 = Executors.newCachedThreadPool();
// 这两种方式创建线程的方式有所不同!
// ExecutorService executorService4 = Executors.newWorkStealingPool();
// ExecutorService executorService5 = Executors.newScheduledThreadPool(5);
try {
for (int i = 0; i < 10; i++) {
executorService1.execute(()->{
System.out.println(Thread.currentThread().getName()+" ok");
});
}
}catch (Exception e){
e.printStackTrace();
} finally {
executorService1.shutdown();
}
}
}
// 源码分析
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(5, 5,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
// 本质 ThreadPoolExecutor()
public ThreadPoolExecutor(int corePoolSize, // 核心线程池大小
int maximumPoolSize, // 最大核心线程池大小
long keepAliveTime, // 超时了没有人调用就会释放
TimeUnit unit, // 超时单位
BlockingQueue<Runnable> workQueue, // 阻塞队列
ThreadFactory threadFactory, // 线程工厂:创建线程的,一般不用动
RejectedExecutionHandler handle) // 拒绝策略
new ThreadPoolExecutor.AbortPolicy() // 队列满了,还有人进来,不处理这个人的,抛出异常
new ThreadPoolExecutor.CallerRunsPolicy() // 哪来的去哪里!由提交任务的线程来处理该任务!
new ThreadPoolExecutor.DiscardPolicy() // 队列满了,丢掉任务,不会抛出异常!
new ThreadPoolExecutor.DiscardOldestPolicy()// 队列满了,尝试去和最早的竞争,也不会抛出异常!
以上为4大拒绝策略!
池的最大的大小如何去设置!
// 获取CPU的核数
Runtime.getRuntime().availableProcessors()
ThreadPoolExecutor 创建线程:
import java.util.concurrent.*;
class test1{
public static void main(String[] args) {
// 最大线程到底该如何定义
// 1、CPU 密集型,几核,就是几,可以保持CPu的效率最高!
// 2、IO 密集型 > 判断你程序中十分耗IO的线程,
// 获取CPU的核数
int core = Runtime.getRuntime().availableProcessors();
ExecutorService executorService = new ThreadPoolExecutor(
2,
core,
3,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,尝试去和最早的竞争,也不会抛出异常!
);
try{
for (int i = 0; i < 10; i++) {
executorService.execute(()->{
System.out.println(Thread.currentThread().getName()+" ok");
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
executorService.shutdown();
}
}
}