线程池
3大方法、7大参数、4种拒绝策略
好处:降低资源的消耗、提高响应的速度、方便管理、
线程池可以理解为银行业务
三大方法
第1大方法:单个线程
ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
第2大方法:创建一个固定的线程池大小
ExecutorService threadExecutor = Executors.newFixedThreadPool(int nThreads);
第3大方法:可伸缩的,遇强则强,遇弱则弱
ExecutorService threadExecutor = Executors.newCachedThreadPool();
import java.util.concurrent.*;
//Executors 工具类 3大方法
public class Demo01 {
public static void main(String[] args) {
//单个线程
// ExecutorService threadPool = Executors.newSingleThreadExecutor();
//固定大小
// ExecutorService threadPool = Executors.newFixedThreadPool(5);
//可伸缩的,遇强则强,遇弱则弱
// ExecutorService threadPool = Executors.newCachedThreadPool();
try {
//最大承载:最大线程池大小 + 阻塞队列
for (int i = 0; i < 10; i++) {
//使用了线程池要用线程池来创建变量
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+" ok");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//线程池用完,程序结束,关闭线程池
threadPool.shutdown();
}
}
}
输出:
第1大方法:单个线程
第2大方法:创建一个固定的线程池大小(5)
第3大方法:可伸缩的,遇强则强,遇弱则弱
7大参数及自定义线程池
源码分析(3大方法)
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,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
其本质都是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) {
//自定义线程池
ExecutorService threadExecutor = new ThreadPoolExecutor(
2,
5,
3,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(3),
Executors.defaultThreadFactory(),
//队列满了,线程数达到最大线程数,还有线程过来,不处理这个线程,抛出异常
// new ThreadPoolExecutor.AbortPolicy()
//哪里来的就去哪里
// new ThreadPoolExecutor.CallerRunsPolicy()
//队列满了,丢掉任务,不会抛出异常
// new ThreadPoolExecutor.DiscardPolicy()
//队列满了,尝试和最早的竞争,竞争失败丢掉任务,也不会抛出异常
new ThreadPoolExecutor.DiscardOldestPolicy()
);
try {
//最大承载:Deque + Max 超过,RejectedExecutionException
for (int i = 0; i < 9; i++) {
//使用了线程池之后,使用线程池来创建线程
threadExecutor.execute(() -> {
System.out.println(Thread.currentThread().getName() + " ok");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//线程池用完,程序结束,关闭线程池
threadExecutor.shutdown();
}
}
}
new ThreadPoolExecutor.AbortPolicy() 输出
new ThreadPoolExecutor.CallerRunsPolicy() 输出
new ThreadPoolExecutor.DiscardPolicy() 输出
new ThreadPoolExecutor.DiscardOldestPolicy() 输出
四种拒绝策略小结
1. 队列满了,线程数达到最大线程数,还有线程过来,不处理这个线程,抛出异常
new ThreadPoolExecutor.AbortPolicy()
2. 哪里来的就去哪里
new ThreadPoolExecutor.CallerRunsPolicy()
3. 队列满了,丢掉任务,不会抛出异常
new ThreadPoolExecutor.DiscardPolicy()
4. 队列满了,尝试和最早的竞争,竞争失败丢掉任务,也不会抛出异常
new ThreadPoolExecutor.DiscardOldestPolicy()
最大线程应该如何设置
-
CPU密集型,几核,就是几,可以保证CPU效率最高
-
IO密集型 (判断你程序中十分耗IO的线程)
如:程序中有15个大型任务,IO十分消耗资源,一般设置为2倍,为30
获取CPU核数
//获取CPU核数
System.out.println(Runtime.getRuntime().availableProcessors());
自定义线程池代码优化
public class Demo01 {
public static void main(String[] args) {
//自定义线程池
ExecutorService threadExecutor = new ThreadPoolExecutor(
4,
Runtime.getRuntime().availableProcessors(),
3,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(3),
Executors.defaultThreadFactory(),
//队列满了,丢掉任务,不会抛出异常
new ThreadPoolExecutor.DiscardPolicy()
);
try {
//最大承载:Deque + Max 超过,RejectedExecutionException
for (int i = 0; i < 10; i++) {
//使用了线程池之后,使用线程池来创建线程
threadExecutor.execute(() -> {
System.out.println(Thread.currentThread().getName() + " ok");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//线程池用完,程序结束,关闭线程池
threadExecutor.shutdown();
}
}
}