JUC:10_3线程池最大线程数设置
线程池最大线程数设置
线程池怎么设计,需要看你的业务,基本分为两种场景
- CPU密集型:CPU是几核的就设置几,这样可以保证CPU的效率最高
- IO密集型:IO操作是十分耗时和占用资源的,因此可以统计系统中的IO任务有多少,然后设置2倍的数值,保证即使IO全部执行,仍有一半线程是可用的。
具体设计要综合业务分析,比如一个线程的操作包括数据操作和IO操作,数据操作是CPU处理,IO操作是硬盘处理,IO的速度比CPU慢很多。
假设1个业务,包括数据操作和IO,耗时10s,
数据处理占用20%的CPU,耗时2s,IO耗时8s。
因此想要占满100%的CPU需要5个业务进来,因此设置5个线程大小,
同理,如果数据处理占用100%CPU,那就1个业务占用是最快的,因此设置1个效率更高,可以有效避免CPU时间片切换。
自定义线程池
Java获取运行环境的CPU核数输出:
System.out.println(Runtime.getRuntime().availableProcessors());
package executor;
import java.util.concurrent.*;
/**
* 线程池七大参数:
* int corePoolSize,//核心线程数大小,即可以并发执行的线程数
* int maximumPoolSize,//最大线程大小
* long keepAliveTime,//超时释放时间
* TimeUnit unit,//释放时间的单位
* BlockingQueue<Runnable> workQueue,//阻塞队列
* ThreadFactory threadFactory,//线程创建工厂,一般不用动
* RejectedExecutionHandler handler//拒绝策略:允许最大线程数=最大线程大小+等待队列数
* <p>
* 线程池四种拒绝策略:
* new ThreadPoolExecutor.AbortPolicy()//默认的拒绝策略,超过会报错:java.util.concurrent.RejectedExecutionException
* new ThreadPoolExecutor.CallerRunsPolicy()//哪来的回哪去,就像你疫情抢菜,里面挤满了,就回家去吧,由调用线程处理
* new ThreadPoolExecutor.DiscardPolicy()//队列满了不报错,丢掉当前任务,不会抛出异常,可以发现只输出了10条
* new ThreadPoolExecutor.DiscardOldestPolicy()//抛弃队列里面最旧的那个(最先等待的),取代它的位置进入队列,并不会和和它进行竞争,直接丢掉队列最旧的元素,不抛出异常
* <p>
* 线程池最大线程数怎么设置?
* - CPU密集型:CPU是几核的就设置几,这样可以保证CPU的效率最高:Java获取运行环境的CPU:Runtime.getRuntime().availableProcessors()
* - IO密集型:IO操作是十分耗时和占用资源的,因此可以统计系统中的IO任务有多少,然后设置2倍的数值,保证即使IO全部执行,仍有一半线程是可用的
*/
public class MyPool {
public static void main(String[] args) {
/**
* int corePoolSize,//核心线程数大小,即可以并发执行的线程数
* int maximumPoolSize,//最大线程大小
* long keepAliveTime,//超时释放时间
* TimeUnit unit,//释放时间的单位
* BlockingQueue<Runnable> workQueue,//阻塞队列
* ThreadFactory threadFactory,//线程创建工厂,一般不用动
* RejectedExecutionHandler handler//拒绝策略:允许最大线程数=最大线程大小+等待队列数,最大为10,我测试拒绝用11个线程
*/
ExecutorService threadPool = new ThreadPoolExecutor(
2,
// Runtime.getRuntime().availableProcessors()//IO密集型设置
5,//测试用5
3,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(5),
Executors.defaultThreadFactory(),
// new ThreadPoolExecutor.AbortPolicy()//默认的拒绝策略,超过会报错
/**
* Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task executor.MyPool$$Lambda$1/1989780873@16b98e56 rejected from java.util.concurrent.ThreadPoolExecutor@7ef20235[Running, pool size = 5, active threads = 5, queued tasks = 5, completed tasks = 0]
* at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
* at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
* at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
* at executor.MyPool.main(MyPool.java:52)
*/
// new ThreadPoolExecutor.CallerRunsPolicy()//哪来的回哪去,就像你疫情抢菜,里面挤满了,就回家去吧,由调用线程处理,不会抛出异常
/**
* pool-1-thread-5...
* pool-1-thread-1...
* pool-1-thread-2...
* pool-1-thread-4...
* main...
* pool-1-thread-3...
* pool-1-thread-5...
* pool-1-thread-1...
* pool-1-thread-2...
* pool-1-thread-4...
* pool-1-thread-3...
*/
// new ThreadPoolExecutor.DiscardPolicy()//队列满了不报错,丢掉当前任务,不会抛出异常,可以发现只输出了10条
/**
* pool-1-thread-2...
* pool-1-thread-3...
* pool-1-thread-4...
* pool-1-thread-5...
* pool-1-thread-1...
* pool-1-thread-1...
* pool-1-thread-3...
* pool-1-thread-4...
* pool-1-thread-5...
* pool-1-thread-2...
*/
new ThreadPoolExecutor.DiscardOldestPolicy()//抛弃队列里面最旧的那个(最先等待的),取代它的位置进入队列,并不会和和它进行竞争,直接丢掉队列最旧的元素,不抛出异常
/**
*
*/
);
try {
// for (int i = 1; i <=5; i++) {
/**
* pool-1-thread-1...
* pool-1-thread-2...
* pool-1-thread-1...
* pool-1-thread-2...
* pool-1-thread-1...
*/
// for (int i = 1; i <=10; i++) {
/**
* pool-1-thread-5...
* pool-1-thread-1...
* pool-1-thread-4...
* pool-1-thread-3...
* pool-1-thread-2...
* pool-1-thread-4...
* pool-1-thread-2...
* pool-1-thread-1...
* pool-1-thread-5...
* pool-1-thread-3...
*/
for (int i = 1; i <= 11; i++) {//允许最大线程数=最大线程大小+等待队列数
/**
* Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task executor.MyPool$$Lambda$1/1989780873@16b98e56 rejected from java.util.concurrent.ThreadPoolExecutor@7ef20235[Running, pool size = 5, active threads = 5, queued tasks = 5, completed tasks = 0]
* at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
* at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
* at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
* at executor.MyPool.main(MyPool.java:52)
* pool-1-thread-5...
* pool-1-thread-4...
* pool-1-thread-3...
* pool-1-thread-2...
* pool-1-thread-1...
* pool-1-thread-5...
* pool-1-thread-4...
* pool-1-thread-2...
* pool-1-thread-1...
* pool-1-thread-3...
*/
threadPool.execute(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "...");
});
}
} finally {
threadPool.shutdown();//线程池关闭,一般放在finally里面执行
}
}
}