java 线程池(ExecutorService与Spring配置threadPoolTaskExecutor)

时间:2021-05-25 18:30:19

一、java ExecutorService实现

  1. 创建ExecutorService变量

private ExecutorService executor = null

      2.执行对应任务时,首先生成线程池

executor = Executors.newFixedThreadPool(线程池大小);

      3.循环执行线程

        for (String str : ids) {

 

                     executor.submit(new Callable<Void>() {

                                         @Override

                                         public Void call() throws Exception {

                                                 ......;//线程执行具体内容

                                                  return null;

                                         }

                     });

         }

          4.关闭线城池, shutdown关闭线城池,执行后程序会继续往下进行,线城池会等待所有线程线程执行完毕后关闭。

executor.shutdown();

          5.设置阻塞等待awaitTermination, awaitTermination的作用是阻塞程序往下进行,使用之后程序会在所有线程执行完毕,关闭线城池之后才可以继续进行。但是如果超过等待时间则会抛出InterruptedException异常

       try {

      //设置最大阻塞时间,所有线程任务执行完成再继续往下执行

      executor.awaitTermination(1, TimeUnit.HOURS);

        long endTime = System.currentTimeMillis();         

      } catch (InterruptedException e) {

      }

@Service

public class DataImpl extends DataService {

         //设置线城池大小

         public static final int THREAD_POOL_FIX_SIZE = 100;

         @Autowired

         private DataDao dataDao;

         //线城池服务

         private ExecutorService executor = null;


         public void createData(Integer totalSize, Integer pageSize) {

                   //由于每次线程执行完毕会关闭线城池,所以要重新获取线城池

                   executor = Executors.newFixedThreadPool(THREAD_POOL_FIX_SIZE);

                   //多线程调用

             for(List<String> id :ids){

                     executor.submit(new Callable<Void>() {

                                         @Override

                                         public Void call() throws Exception {

                                                  createData(id);

                                                  return null;

                                         }

                     });

             }

         //关闭线城池

           executor.shutdown();

      try {

      //设置最大阻塞时间,所有线程任务执行完成再继续往下执行

      executor.awaitTermination(24, TimeUnit.HOURS);

      long endTime = System.currentTimeMillis();

  

      logger.info("=====================结束,用时"+ (endTime-startTime) + "毫秒" );

      

      } catch (InterruptedException e) {

      logger.info("======================超时" );

      }

         }


         private void createData(String id){

                   ……

         }

}

 

*注:1.Executors.newFixedThreadPool(THREAD_POOL_FIX_SIZE);要在每次调用方法的时候创建,线程全部执行完成之后shundown(),释放所有线程,这样可以保证执行任务时生成足够线程,线程执行完立即释放。

         2. ExecutorService可以写在没个类内,单独问此类使用,不同类之间互不干扰;也可以也成公用方法,写成公用方法后也会变成多类(多任务共享)同Spring线城池类似。

二、Spring 配置线程池(threadPoolTaskExecutor)

         

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

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

maxPoolSize   线程池维护线程的最大数量

queueCapacity 线程池所使用的缓冲队列

rejectedExecutionHandler 线程池拒绝处理策略

当一个任务通过execute(Runnable)方法欲添加到线程池时:

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

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

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

l  如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程 maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。

l  当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。

*注:1.spring 配置的线城池(threadPoolTaskExecutor)由于是spring创建注入的,在首次使用之后,会一直保持corePoolSize个空闲线程,它只会把多余的空闲线程在keepAliveSeconds 时间之后释放,而且线城池不能调用shutdown()方法,否则再次调用,由于线程池已经关闭,会报错。

   2. threadPoolTaskExecutor也可以在配置文件配置多个线城池,防止多有任务之间竞争,或者由于不同任务使用的线城池大小不同等情况。

 

 

三、ExecutorService与threadPoolTaskExecutor对比

 

 

threadPoolTaskExecutor

ExecutorService(Executors.newFixedThreadPool(线程池大小);)

创建方式

配置文件配置比较方便简单

可以没有类中单独编写,也可以写成通用类调用

核心线程数

corePoolSize

线程池大小

最大线程数

maxPoolSize  

线程池大小

线程所允许的空闲时间

keepAliveSeconds 

0

缓冲队列大小

queueCapacity

MAX_VALUE = 0x7fffffff

线程池拒绝处理策略

 

rejectedExecutionHandler

缓冲队列那么大不会拒绝吧。

线程执行完处理

保留核心线程数量个线程继续等待连接,不能shutdown,awaitTermination

可以shutdown,awaitTermination方便处理一些所有线程全部执行完才能够调用的服务接口等。