线程池
池化技术
程序的运行会占用系统的资源,为了优化资源的使用=>池化技术
比如:线程池,连接池,内存池…
池化技术:事先准备好一些资源,有人要用就来这里来取,用完之后返还
线程池的好处
- 降低资源的消耗
- 提高响应的速度
- 方便管理
线程复用,可以控制最大并发数,管理线程
线程池的使用
三大操作
- Executors.newSingleThreadExecutor();//单个线程
- Executors.newFixedThreadPool(5);//创建一个固定的线程池大小
- Executors.newCachedThreadPool();//可伸缩的
//ExecutorService threadPool= Executors.newSingleThreadExecutor();//只有一个线程在执行
//ExecutorService threadPool= Executors.newFixedThreadPool(5);//同时最多有5个线程在执行
ExecutorService threadPool= Executors.newCachedThreadPool();//遇强则强,测试的时候是同时有10个在执行
long start_time = System.currentTimeMillis();
try {
for(int i=0;i<10;i++){
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName());
});
}
} finally {
threadPool.shutdown();//线程池用完之后要关闭
System.out.println(System.currentTimeMillis()-start_time);
}
七大参数
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>());
}
//本质是ThreadPoolExecutor()
public ThreadPoolExecutor(int corePoolSize,//核心线程大小
int maximumPoolSize,//最大核心线程大小
long keepAliveTime,//超时了多少没有人调用就会释放
TimeUnit unit,//超时单位
BlockingQueue<Runnable> workQueue,//阻塞队列
ThreadFactory threadFactory,//线程工厂,创建线程的,一般不动
RejectedExecutionHandler handler//拒绝策略) {
阿里开发手册上强制要求使用ThreadPoolExecutor
【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这
样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
说明:Executors 返回的线程池对象的弊端如下:
1) FixedThreadPool 和 SingleThreadPool:
允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
2) CachedThreadPool:
允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。
最大核心线程如何设置
- CPU密集型 几核就是几,保持CPU效率最高
Runtime.getRuntime().availableProcessors();//获取CPU核数
- IO密集型 判断程序中十分耗IO的线程
四个拒绝策略
//自定义线程池
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3,
5,
10,
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.某个策略);
for(int i=0;i<10;i++){
threadPoolExecutor.execute(()->{
System.out.println(Thread.currentThread().getName());
});
}
-
AbortPolicy直接丢弃任务,并抛出RejectedExecutionException异常。
... pool-1-thread-4 pool-1-thread-5//执行了八个 Exception in thread "main" java.util.concurrent.RejectedExecutionException
-
CallerRunsPolicy哪来到哪去
... pool-1-thread-4 main pool-1-thread-3 ...//一共十个
-
DiscardPolicy直接丢弃任务,不抛出异常。
pool-1-thread-1 pool-1-thread-5 pool-1-thread-4 pool-1-thread-3 ...//8个
-
DiscardOldestPolicy尝试和最早的竞争
... pool-1-thread-4 pool-1-thread-2 pool-1-thread-3 pool-1-thread-5//一共8个