说明:线程池优势
主要特点:线程复用,控制并发,线程管理。
①提高响应速度:项目运行线程池创建,当任务到达时,不需要在创建线程,直接拿来使用就行【线程未达到核心线程数】
②降低资源消耗:重复利用创建好的线程以减少创建线程和销毁线程造成的消耗
③提高线程的可管理性:线程是稀缺资源,如果无限制的创建,会很消耗系统资源,严重的情况会影响系统的稳定性;线程池可以统一管理线程的分配和监控。
线程池参数配置说明
int corePoolSize【核心线程数】:线程池中的常驻线程,可理解为当值线程
int maximumPoolSize【最大线程数】:线程池中能容纳的最大可执行线程数,最大线程数包含核心线程数,即最大线程数大于核心线程数
long keepAliveTime【多余空闲线程存活时间】:当前线程池中线程数量大于核心线程数量时,大于数量存活的时间
TimeUnit unit【多余空闲线程存活时间单位】:需要和多余线程池存活时间
BlockingQueue<Runnable> workQueue【阻塞队列】:当请求任务大于核心线程数量时,多的任务就会被放到队列中
ThreadFactory threadFactory【线程工厂】:有时重写线程工厂可以更好的对线程执行任务监控
RejectedExecutionHandler handler【拒绝策略】:当阻塞队列满时,线程池会对新来的任务进行拒绝,①AbrotPolicy(默认):直接抛出RejectedExecutionException异常,组织系统正常运行;②CallerRunsPolicy:不会抛弃任务,不会抛出异常,而是将某些任务回退到调用者;③DiscardOldestPolicy:抛弃队列中等待最久的任务,把新的任务加入队列中尝试执行;④DiscardPolicy:直接丢弃任务,不做任何处理,也不抛异常,如果业务方面允许业务丢失,可以选择该方案
线程池执行流程
①项目运行,线程池创建
②当有任务请求时:
如果正在运行的线程数量小于核心线程数【corePoolSize】,该任务会马上被执行;
如果正在运行的线程数量大于或等于核心线程数【corePoolSize】,该任务会被放到阻 塞队列中;
如果阻塞队列中存放的任务满且运行线程小于最大线程数【maximumPoolSize】,会创建非核心线程并执行该任务;
如果队列满且执行的线程数达到最大线程数【maximumPoolSize】,线程池会执行拒绝策略;
③随着时间的推移,可执行的任务渐渐减少,当一个线程无任务执行且无任务执行的时间为线程的多余空闲线程存活时间【keepAliveTime】,那么该线程会被销毁。
注:线程池中的线程数量最终会收缩到核心线程大小
1.Java自带线程池说明
①Executors.newSingleThreadExecutor()
//就是单线程:创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序执行。
public static ExecutorService newSingleThreadExecutor() {
return new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
②Executors.newCachedThreadPool()
//线程数量是没有大小限制的,当新的线程来了直接创建,同样会造成资源消耗殆尽:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
③Executors.newFixedThreadPool(4)
//阻塞队列大小是没有大小限制的,内存会溢出:创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
2.自定义线程池【springboot线程池整合在上篇文章】
import java.util.concurrent.*;
/**
* @return {@link }
* @throws
* @author 李庆伟
* @date 2022/11/4 16:11
*/
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
4,
8,
30,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(8),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
poolExecutor.execute(()->{
System.out.println(Thread.currentThread().getThreadGroup()+" "+
Thread.currentThread().getName()+"线程池........");
});
poolExecutor.shutdown();
}
}