一、线程池
1、概念
池化技术:
- 本质:占用系统的资源!
- 事先准备好一些资源,有人要用,就来我这里拿,用完之后还给我。
2、优点
- 降低系统资源的消耗
- 提高响应的速度
- 方便管理
3、三大方法
- Executors 工具类的3大方法
①、 创建单个线程的线程池:Executors.newSingleThreadExecutor();
②、创建一个固定大小的线程池: Executors.newFixedThreadPool(5);
③、 创建一个可伸缩的线程池:Executors.newCachedThreadPool(); - 代码演示一:开启单线程线程池
public class ThreadPool {
public static void main(String[] args) {
//创建单个线程的线程池
ExecutorService threadPool = Executors.newSingleThreadExecutor();
// ExecutorService threadPool = Executors.newFixedThreadPool(5);
// ExecutorService threadPool = Executors.newCachedThreadPool();
try{
for (int i=1;i<=100;i++){
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"--->ok");
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
threadPool.shutdown();
}
}
}
运行结果:
- 开启固定大小的线程池
public class ThreadPool {
public static void main(String[] args) {
//创建单个线程的线程池
// ExecutorService threadPool = Executors.newSingleThreadExecutor();
ExecutorService threadPool = Executors.newFixedThreadPool(5);
// ExecutorService threadPool = Executors.newCachedThreadPool();
try{
for (int i=1;i<=100;i++){
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"--->ok");
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
threadPool.shutdown();
}
}
}
运行结果:
- 开启可伸缩的线程池
public class ThreadPool {
public static void main(String[] args) {
//创建单个线程的线程池
// ExecutorService threadPool = Executors.newSingleThreadExecutor();
// ExecutorService threadPool = Executors.newFixedThreadPool(5);
ExecutorService threadPool = Executors.newCachedThreadPool();
try{
for (int i=1;i<=100;i++){
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"--->ok");
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
threadPool.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>());
}
4、七大参数分析
// 本质ThreadPoolExecutor()
public ThreadPoolExecutor(
// 核心线程池大小
int corePoolSize,
// 最大核心线程池大小
int maximumPoolSize,
// 超时没有人调用就会释放
long keepAliveTime,
// 超时单位
TimeUnit unit,
// 阻塞队列
BlockingQueue<Runnable> workQueue,
// 线程工厂:创建线程的,一般 不用动
ThreadFactory threadFactory,
// 拒绝策略
RejectedExecutionHandler handle ) {
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;
}
- 因为实际开发中工具类Executors 不安全,所以需要手动创建线程池,自定义7个参数。
public class MyThreadPool {
public static void main(String[] args) {
//自定义线程池
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
// int corePoolSize, 核心线程池大小(候客区窗口2个)
2,
// int maximumPoolSize, 最大核心线程池大小(总共5个窗口)
5,
// long keepAliveTime, 超时3秒没有人调用就会释,放关闭窗口
3,
// TimeUnit unit, 超时单位 秒
TimeUnit.SECONDS,
// 阻塞队列(候客区最多3人)
new LinkedBlockingDeque<>(3),
// 默认线程工厂
Executors.defaultThreadFactory(),
// 4种拒绝策略之一:队列满了,尝试去和最早的竞争,也不会抛出异常!
new ThreadPoolExecutor.DiscardOldestPolicy()
);
try{
for (int i=1;i<=10;i++){
threadPoolExecutor.execute(()->{
System.out.println(Thread.currentThread().getName()+"--->ok");
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
//关闭线程池
threadPoolExecutor.shutdown();
}
}
}
- 运行结果:
可以看到只有8调线程运行,因为线程池最大数为5,等待队列为3,总共为8,超过的线程,尝试去和最早的竞争,不会抛出异常!
5、四大拒绝策略
- new ThreadPoolExecutor.AbortPolicy() :当线程池满了,还有线程要进来,就抛出异常。
- new ThreadPoolExecutor.CallerRunsPolicy():A线程叫B线程去让C线程做事情,C线程拒绝了,让B线程叫A线程去做。
- new ThreadPoolExecutor.DiscardPolicy() :线程池满了,丢弃还没有拿到资源的线程。
- new ThreadPoolExecutor.DiscardOldestPolicy() :线程池满了,让最后进来的线程和最开始进来的线程进行竞争。
6、线程池最大连接数调优
①、CPU密集型:你的电脑或者服务器时几核的,就把最大容量设置为几,这样可以保持CPU的效率最高!
②、IO 密集型:判断你程序中十分消耗IO资源的线程,比如这样的线程有15个,IO密集型参数(最大线程数)就设置为大于15即可,一般选择两倍。