线程池`基础`

Posted duduchong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程池`基础`相关的知识,希望对你有一定的参考价值。


种类

  • Executors.newCachedThreadPool
    ?定义:无界线程池,可自动回收
    ?缺点:涌入大量任务时会大量创建线程

  • Executors.newFixedThreadPool
    ?定义:线程池中的线程数固定大小,超出的线程会在队列中等待
    ?缺点:任务数量过大效率不高

  • Executors.newScheduledThreadPool
    ?定义:创建一个定长线程池,支持定时及周期性任务执行

  • Executors.newSingleThreadExecutor
    ?定义:单个后台线程


总结

深入源码,你会发现:这几个方法都调用了ThreadPoolExecutor的构造函数,只要研究ThreadPoolExecutor构造函数就行


补充 Executors类创建的线程池对象多有弊端

  • FixedThreadPool、SingleThreadPool ,允许阻塞队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。
  • CachedThreadPool、ScheduledThreadPool,允许创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM 。

区别

  • xexecutor.submit()
  • xexecutor.execute()

submit会返回future,可以从中拿到线程执行结果



属性

corePoolSize
?核心线程数,平时保留的线程数

maximumPoolSize
?最大线程数,当阻塞队列都放不下时,启动的新线程的最大数量

keepAliveTime
?超出核心线程数的那些线程,它们的保留时长

unit
?TimeUnit,线程保留时间的单位

workQueue
BlockingQueue,阻塞队列,存放来不及执行的线程

  • ArrayBlockQueue:构造函数一定要传大小
  • LinkedBlockQueue:默认大小为Integer.MAX_VALUE,大量任务会耗尽内存
  • SynchronousQueue:同步队列,一个没有存储空间的阻塞队列,将任务交付给工作线程
  • PriorityBlockingQueue:优先队列

threadFactory
?ThreadFactory,线程工厂

handler
?RejectedExecutionHandler,饱和策略。

  • 理解:核心线程corePoolSize、任务队列workQueue、最大线程 maximumPoolSize,三者都满了,此时使用handler处理被拒绝的任务
    策略:见拒绝策略

构造方法

public ThreadPoolExecutor(
    int corePoolSize,
    int maximumPoolSize,
    long keepAliveTime,
    TimeUnit unit,
    BlockingQueue<Runnable> workQueue,
    ThreadFactory threadFactory,
    RejectedExecutionHandler handler){}

拒绝策略

  • AbortPolicy(默认):丢弃任务、且抛出异java.util.concurrent.RejectedExecutionException
  • CallerRunsPolicy:主线程执行该任务,下一任务继续往线程池中添加(重复此过程)。可有效降低添加线程的速度
  • DiscardOldestPolicy:抛弃队列最前面的任务,尝试当前任务(重复此过程)
  • DiscardPolicy:丢弃任务,但不抛出异常

实践

springboot配置线程池

@Configuration
public class ThreadPoolTaskConfig {
    @Bean
    public Executor executor() {
?       ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

        // 可用CPU数量;不小于1
        int core = Runtime.getRuntime().availableProcessors();
        // 核心线程数
        executor.setCorePoolSize(core);
        // 最大线程数**
        executor.setMaxPoolSize(core*2+1);
        // 除核心线程外的线程存活时间**
        executor.setKeepAliveSeconds(3);
        // 默认使用SynchronousQueue,若传值>0,底层队列使用LinkedBlockingQueue
        executor.setQueueCapacity(40);
        // 线程名称前缀
        executor.setThreadNamePrefix("-");
        // 设置拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

?       return executor;
    }
}





















以上是关于线程池`基础`的主要内容,如果未能解决你的问题,请参考以下文章

Java线程池详解

Java线程池详解

Java 线程池详解

Java线程池详解

线程池与并行度

Motan在服务provider端用于处理request的线程池