一、什么是线程池
线程池的优势:
线程池做的工作只要是控制运行的线程数量, 处理过程中将任务放入队列 ,然后在线程创建后启动这些任务, 如果线程数量超过了最大数量,超出数量的线程排队等候 ,等其他线程执行完毕,再从队列中取出任务来执行。
它的主要特点为: 线程复用;控制最大并发数;管理线程。
第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的销耗。
第二:提高响应速度。当任务到达时,任务可以不需要等待线程创建就能立即执行。
第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会销耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
二、线程池的三大方法
1)ExecutorService threadPool= Executors.newFixedThreadPool(5);//一池五个工作线程
2)ExecutorService threadPool= Executors.newSingleThreadScheduledExecutor();//一池1个
3)ExecutorService threadPool= Executors.newCachedThreadPool();//一池N个工作线程
代码:
package com.cb.demo.example;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class MyThreadPool {
public static void main(String[] args) {
//ExecutorService threadPool= Executors.newFixedThreadPool(5);//一池五个工作线程
// ExecutorService threadPool= Executors.newSingleThreadScheduledExecutor();//一池1个
ExecutorService threadPool= Executors.newCachedThreadPool();//一池N个工作线程
try
{
for (int i = 0; i <20 ; i++) {
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"\t 办理业务");
});
//try{ TimeUnit.SECONDS.sleep(1);}catch(InterruptedException e){e.printStackTrace();}
}
}catch(Exception e){
e.printStackTrace();
}finally{
threadPool.shutdown();
}
}
}
三、流程和7大参数
核心线程--->阻塞队列--->最大线程池---->拒绝策略
源码:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
corePoolSize:核心线程数
maximumPoolSize:最大线程数据 (CPU型 :cpu核数+1~2)
keepAliveTime:空闲线程存活时间
TimeUnit:存活时间单位
BlockingQueue:阻塞队列(一般使用new LinkedBlockingQueue<>(3),)
ThreadFactory:线程工厂 (使用默认)
RejectedExecutionHandler:拒绝策略
1、AbortPolicy(默认):直接抛出RejectedExecutionException异常阻止系统正常运行
2、CallerRunsPolicy:“调用者运行”一种调节机制,该策略既不会抛弃任务,也不
会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量。
3、DiscardOldestPolicy:抛弃队列中等待最久的任务,然后把当前任务加人队列中
尝试再次提交当前任务。
4、DiscardPolicy:该策略默默地丢弃无法处理的任务,不予任何处理也不抛出异常。
如果允许任务丢失,这是最好的一种策略。
工作原理:
1、在创建了线程池后,开始等待请求。
2、当调用 execute() 方法添加一个请求任务时,线程池会做出如下判断:
2.1如果正在运行的线程数量小于 corePoolSize ,那么马上创建线程运行这个任务;
2.2如果正在运行的线程数量大于或等于 corePoolSize ,那么将这个任务 放入队列 ;
2.3如果这个时候队列满了且正在运行的线程数量还小于 maximumPoolSize ,那么还是要创建非核心线程立刻运行这个任务;
2.4如果队列满了且正在运行的线程数量大于或等于 maximumPoolSize ,那么线程池会 启动饱和拒绝策略来执行 。
3、当一个线程完成任务时,它会从队列中取下一个任务来执行。
4、当一个线程无事可做超过一定的时间( keepAliveTime )时,线程会判断:
如果当前运行的线程数大于 corePoolSize ,那么这个线程就被停掉。
所以线程池的所有任务完成后, 它最终会收缩到 corePoolSize 的大小 。
代码:
package com.cb.demo.example;
import java.util.concurrent.*;
public class MyThreadPool {
public static void main(String[] args) {
ExecutorService threadPool=new ThreadPoolExecutor(2,
5,
2L,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy());// new ThreadPoolExecutor.AbortPolicy(),new ThreadPoolExecutor.CallerRunsPolicy(),new ThreadPoolExecutor.DiscardPolicy()
try
{
for (int i = 0; i <9 ; i++) {
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"\t 办理业务");
});
// try{ TimeUnit.SECONDS.sleep(1);}catch(InterruptedException e){e.printStackTrace();}
}
}catch(Exception e){
e.printStackTrace();
}finally{
threadPool.shutdown();
}
}
private static void initPool() {
//ExecutorService threadPool= Executors.newFixedThreadPool(5);//一池五个工作线程
// ExecutorService threadPool= Executors.newSingleThreadScheduledExecutor();//一池1个
ExecutorService threadPool= Executors.newCachedThreadPool();//一池N个工作线程
try
{
for (int i = 0; i <20 ; i++) {
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"\t 办理业务");
});
//try{ TimeUnit.SECONDS.sleep(1);}catch(InterruptedException e){e.printStackTrace();}
}
}catch(Exception e){
e.printStackTrace();
}finally{
threadPool.shutdown();
}
}
}