线程池需要学
- 三大方法
- 七大参数
- 四大拒绝策略
三大方法:
- Executors.newSingleThreadExecutor();
- 创建单个线程的线程池
- Executors.newFixedThreadPool(int count);
- 创建指定数量的线程的线程池
- Executors.newCachedThreadPool();
- 根据使用数量自动扩容的线程池
//创建单个线程的线程池
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()+" Running");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
创建三个对象,分别十次循环创建线程
Executors.newSingleThreadExecutor();
Executors.newFixedThreadPool(int count);
Executors.newCachedThreadPool();
七大参数
银行办理业务:柜台1 2号在办理业务,3 4 5 号暂停业务,所以最大线程数就是5个,核心线程数就是2个,候客区的三个就是阻塞队列,当还有人来,没有地方了,要么再等,要么离开,这就是拒绝策略。
- corePoolSize 核心线程数
- maximumPoolSize 最大线程数
- keepAliveTime 当线程大于最大线程数,则会根据超时时间进行活性检查,一旦超过时间便销毁线程
- TimeUnit 超时单位
- BlockingQueue<Runnable> 阻塞队列
- ThreadFactory 线程工厂,创建线程的
- RejectedExecutionHandler 拒绝策略
我们使用线程池,一定不要使用Executors创建,我们要自定义线程池。
创建线程池eg:
ExecutorService threadPool = new ThreadPoolExecutor(
3, //核心线程数
5, //最大线程数
2, //超时时间,当线程大于最大线程数,则会根据超时时间进行活性检查,
// 一旦超过时间便销毁线程
TimeUnit.SECONDS, //超时时间单位
new ArrayBlockingQueue<>(3),//阻塞队列
Executors.defaultThreadFactory(), //线程工厂
new ThreadPoolExecutor.AbortPolicy() //拒绝策略
);
最大线程承载:maximumPoolSize+BlockingQueue
一旦超过了最大承载,便会被拒绝策略接收
四大拒绝策略:
- new ThreadPoolExecutor.Abortpolicy()
- 超过最大承载,则会抛出异常
- new ThreadPoolExecutor.CallerRunsPolicy()
- 交给主线程处理,不抛出异常
- new ThreadExecutor.DiscardPolicy()
- 队列满了,不会抛出异常,丢弃被拒绝的任务
- new ThreadExecutor.DiscardOldestPolicy()
- 队列满了,尝试和最开始的线程竞争,不抛出异常
package com.xiaofei.pool;
import java.util.concurrent.*;
/**
* @author xiaofei
* @version 1.0
* @date 2020/9/10 18:19
*/
public class ThreadPoolTest {
public static void main(String[] args) {
// ExecutorService threadPool = Executors.newSingleThreadExecutor();
// ExecutorService threadPool = Executors.newFixedThreadPool(5);
// ExecutorService threadPool = Executors.newCachedThreadPool();
ExecutorService threadPool = new ThreadPoolExecutor(
3, //核心线程数
5, //最大线程数
2, //当线程大于最大线程数,则会根据超时时间进行活性检查,
// 一旦超过时间便销毁线程
TimeUnit.SECONDS, //超时时间单位
new ArrayBlockingQueue<>(3),//阻塞队列
Executors.defaultThreadFactory(), //线程工厂
new ThreadPoolExecutor.DiscardOldestPolicy()
// new ThreadPoolExecutor.DiscardPolicy()
// new ThreadPoolExecutor.CallerRunsPolicy()
// new ThreadPoolExecutor.AbortPolicy() //拒绝策略
);
try {
for (int i = 0; i < 9; i++) {
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+" Running");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
}
如何判断最大线程数?
- CPU密集型
- 查看cpu是几核的,根据核数判断最大线程数
- Runtime.getRuntime().availableProcessors();
- IO密集型
- 通过查看有多少个十分耗IO的线程,一般最大值设置为其两倍
package com.xiaofei.pool;
import java.util.concurrent.*;
/**
* @author xiaofei
* @version 1.0
* @date 2020/9/11 13:00
*/
public class ThreadPool2 {
public static void main(String[] args) {
//获取电脑的核数
final int MAX_POOL_SIZE = Runtime.getRuntime().availableProcessors();
ExecutorService threadPool = new ThreadPoolExecutor(
3,
MAX_POOL_SIZE,
3,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardPolicy()
);
try {
for (int i = 0; i < (MAX_POOL_SIZE + 3); i++) {
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+" Running");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
}