线程池基础可以参考 https://www.cnblogs.com/enhance/p/11009997.html
线程池创建方式:
- 使用 Executors 类,Executors 类是 Java 中用于创建线程池的工厂类,它提供了多种静态方法来创建不同类型的线程池
newFixedThreadPool:
使用的构造方式为new ThreadPoolExecutor(var0, var0, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()),设置了corePoolSize=maxPoolSize,keepAliveTime=0(此时该参数没作用),无界队列,任务可以无限放入,当请求过多时(任务处理速度跟 上任务提交速度造成请求堆积)可能导致占用过多内存或直接导致OOM异常
newSingleThreadExector:
使用的构造方式为new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), var0),基本同newFixedThreadPool,但是将线程数设置为了1,单线程,弊端和newFixedThreadPool一致
newCachedThreadPool:
使用的构造方式为new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue()),corePoolSize=0,maxPoolSize为很大的数,同步移交队列,也就是说不维护常驻线程(核心线程),每次来请求直接创建新线程来处理任务,也不 使用队列缓冲,会自动回收多余线程,由于将maxPoolSize设置成Integer.MAX_VALUE,当请求很多时就可能创建过多的线程,导致资源耗尽OOM
newScheduledThreadPool:
使用的构造方式为new ThreadPoolExecutor(var1, 2147483647, 0L, TimeUnit.NANOSECONDS, new ScheduledThreadPoolExecutor.DelayedWorkQueue()),支持定时周期性执行,注意一下使用的是延迟队列,弊端同newCachedThreadPool一致
- 使用 ThreadPoolExecutor 类,ThreadPoolExecutor 是 Java 中线程池的一个核心类,它提供了更细粒度的控制来创建和管理线程池 (如下例)
- 使用 Future 和 Callable,Future 和 Callable 是并发编程中非常重要的两个接口,它们通常与 ExecutorService 一起使用来执行异步任务。 (个人感觉这就是用executor创建线程池)
- 使用 Spring 的 ThreadPooltaskExecutor,ThreadPoolTaskExecutor 是一个基于 java.util.concurrent.ThreadPoolExecutor 的扩展,提供了更丰富的配置选项和与Spring集成的特性
线程池5种状态
- RUNNING:正常运行状态,可接收新任务,可处理阻塞队列中的任务
- SHUTDOWN:不会接收新任务,但会处理阻塞队列剩余任务
- STOP:会中断正在执行的任务,并抛弃阻塞队列任务
- TIDYING:任务全执行完毕,活动线程为 0,即将进入终结
- TERMINATED:终结状态
项目开发中线程池推荐创建方式
不允许使用Executors创建,而是通过ThreadPoolExecutor创建
Executors创建方式:
ExecutorService service= Executors.newFixedThreadPool(5);
public void test(){
service.execute(()->{...});
}
因为Executors创建 newFixedThreadPool & newSingleThreadExector容易造成任务无限创入LinkedBlockingQueue造成oom;对于newCachedThreadPool&newScheduledThreadPool容易造成线程无限创建造成oom
ThreadpoolExecutor创建方式:
@Configuration public class ThreadConfig { @Bean(value="threadPoolInstance") public ExecutorService createThreadPoolInstance(){
////通过guava类库的ThreadFactoryBuilder来实现线程工厂类并设置线程名称 ThreadFactory threadFactory=new ThreadFactoryBuilder(). setNameFormat("thread-pool-%d").build(); ExecutorService threadPool=new ThreadPoolExecutor( 5, 10, 60L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100), new ThreadPoolExecutor.AbortPolicy()); return threadPool; } }
@Service public class BusinessThreadPoolService {
//通过name=threadPoolInstance引用线程池实例 @Resource(name="threadPoolInstance") private ExecutorService executorService; public void execute(){ long current=System.currentTimeMillis(); executorService.execute(new Runnable() { @Override public void run() { //business code... } } }); System.out.println(System.currentTimeMillis()-current); }
}
线程池任务提交方式
execute()
execute只接受runnable類型參數,不可以返回执行结果
public void execute(){ long current=System.currentTimeMillis(); executorService.execute(new Runnable() { @Override public void run() { //business code } }); System.out.println(System.currentTimeMillis()-current); }
submit()
接收runnable/callable类型参数,其中callable允许返回执行结果,允许抛出异常
通过executor.submit提交一个callable,返回一个Future,然后通过这个Future的get方法取得返回值
public void submit() throws ExecutionException, InterruptedException {
long current=System.currentTimeMillis();
Future future=executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception{
// business code
return "this is a test";
}
});
System.out.println("callable result:"+future.get());
}
执行结果:
callable result:this is a test
参考文献:
https://blog.csdn.net/qq_40428665/article/details/121651421
https://blog.csdn.net/qq_25806863/article/details/71214033
https://baijiahao.baidu.com/s?id=1701886340868428458&wfr=spider&for=pc
浙公网安备 33010602011771号