线程池创建使用

Posted brant

tags:

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

最近项目中引入了阿里的规范插件,扫描发现之前创建线程池的方式有问题.

比如:Executors.newFixedThreadPool(poolSize) 和 Executors.newCachedThreadPool();

线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

说明:Executors返回的线程池对象的弊端如下:

newFixedThreadPool和newSingleThreadExecutor:主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。

newCachedThreadPool和newScheduledThreadPool:主要问题是线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM。

 

推荐示例1

 

 //org.apache.commons.lang3.concurrent.BasicThreadFactory

    ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,

        new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());

推荐示例2

 

ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()

        .setNameFormat("demo-pool-%d").build();

 

    //Common Thread Pool

    ExecutorService pool = new ThreadPoolExecutor(5, 200,

         0L, TimeUnit.MILLISECONDS,

         new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());

 

    pool.execute(()-> System.out.println(Thread.currentThread().getName()));

    pool.shutdown();//gracefully shutdown

      

推荐示例3

 

 

<bean id="userThreadPool"

        class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">

        <property name="corePoolSize" value="10" />

        <property name="maxPoolSize" value="100" />

        <property name="queueCapacity" value="2000" />

 

    <property name="threadFactory" value= threadFactory />

        <property name="rejectedExecutionHandler">

            <ref local="rejectedExecutionHandler" />

        </property>

    </bean>

    //in code

    userThreadPool.execute(thread);

 

 

线程池类java.util.concurrent.ThreadPoolExecutor构造方法:

 

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue,

RejectedExecutionHandler handler)

corePoolSize: 线程池维护线程的最少数量

maximumPoolSize:线程池维护线程的最大数量

keepAliveTime: 线程池维护线程所允许的空闲时间

unit: 线程池维护线程所允许的空闲时间的单位

workQueue: 线程池所使用的缓冲队列

handler: 线程池对拒绝任务的处理策略

 

但有新任务时

如果线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。

如果线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。

如果线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。

如果线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。

 

处理任务的优先级为:

核心线程corePoolSize、

任务队列workQueue、

最大线程maximumPoolSize,

如果三者都满了,使用handler处理被拒绝的任务。

 

keepAliveTime: 当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被回收。

unit: 可选的参数为java.util.concurrent.TimeUnit中的几个静态属性:NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS。

workQueue可使用:ArrayBlockingQueue 或者LinkedBlockingQueue

handler有四个选择:

ThreadPoolExecutor.AbortPolicy() 抛出java.util.concurrent.RejectedExecutionException异常

ThreadPoolExecutor.CallerRunsPolicy()重试添加当前的任务,他会自动重复调用execute()方法

ThreadPoolExecutor.DiscardOldestPolicy()抛弃旧的任务

ThreadPoolExecutor.DiscardPolicy()抛弃当前的任务

 

代码样例:

public class ThreadPoolExecutorBuilder {

   private int corePoolSize;//核心线程数
   private int maxPoolSize;//最大线程数
   private long keepAliveTime;//超线程最大空闲时间
   private TimeUnit timeUnit;//单位
   private BlockingQueue<Runnable> workQueue;//工作队列
   private RejectedExecutionHandler handler;//线程池对拒绝任务的处理策略
   private ThreadFactory threadFactory;//线程工厂

   //构造函数-初始化参数默认值
   public ThreadPoolExecutorBuilder(){
      int processors=Runtime.getRuntime().availableProcessors();//读取服务器CPU核心数
      this.corePoolSize=processors;
      this.maxPoolSize=processors*2;
      this.timeUnit=TimeUnit.SECONDS;
      this.keepAliveTime=0;
      this.threadFactory=new ThreadFactoryBuilder().setNameFormat("ThreadPoolExecutor-pool-%d").build();
      this.handler =new ThreadPoolExecutor.AbortPolicy();//饱和抛异常
      this.workQueue =new LinkedBlockingQueue<Runnable>(1024);
   }

   //创建线程池
   public ThreadPoolExecutor build(){
      return new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, timeUnit, workQueue, threadFactory, handler);
   }

   //设置线程数
   public ThreadPoolExecutorBuilder setCapacity(int corePoolSize,int maxPoolSize){
      this.corePoolSize=corePoolSize;
      this.maxPoolSize=maxPoolSize;
      return this;
   }

   //设置线程最大空闲时间
   public ThreadPoolExecutorBuilder setKeepAliveTime(long keepAliveTime,TimeUnit timeUnit){
      this.keepAliveTime=keepAliveTime;
      this.timeUnit=timeUnit;
      return this;
   }
   //设置线程队列
   public ThreadPoolExecutorBuilder setWorkqueue(BlockingQueue<Runnable> workQueue){
      this.workQueue=workQueue;
      return this;
   }
   //设置队列处理策略
   public ThreadPoolExecutorBuilder setRejectedExecutionHandler(RejectedExecutionHandler handler){
      this.handler=handler;
      return this;
   }
   //设置线程工厂
   public ThreadPoolExecutorBuilder setThreadFactory(ThreadFactory threadFactory){
      this.threadFactory=threadFactory;
      return this;
   }
}

  

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

Java线程池详解

Java线程池详解

Java 线程池详解

线程池与并行度

图解为什么要使用线程池?

IDEA对新建java线程池的建议