如何基于ThreadPoolExecutor创建线程池并操作

 更新时间:2020年11月10日 09:25:26   作者:牛鼻子老赵  
这篇文章主要介绍了如何基于ThreadPoolExecutor创建线程池并操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

日常工作中很多地方很多效率极低的操作,往往可以改串行为并行,执行效率往往提高数倍,废话不多说先上代码

1、用到的guava坐标

<dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <version>18.0</version>
    </dependency>

2、创建一个枚举保证线程池是单例

package com.hao.service;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import com.google.common.util.concurrent.ThreadFactoryBuilder;

public enum ExecutorManager {

  INSTANCE;

  private ExecutorManager() {

  }

  private static int AVAILABLEPROCESSORS = Runtime.getRuntime().availableProcessors();

  public static final ThreadPoolExecutor threadPoolExecutor =
    new ThreadPoolExecutor(AVAILABLEPROCESSORS * 50, AVAILABLEPROCESSORS * 80, 0L, TimeUnit.MILLISECONDS,
      new LinkedBlockingQueue<Runnable>(AVAILABLEPROCESSORS * 2000),
      new ThreadFactoryBuilder().setNameFormat("ExecutorManager-pool-Thread-%d").build());
}

3、创建一个方法类

package com.hao.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import javax.annotation.PostConstruct;

import org.springframework.stereotype.Service;

import com.google.common.base.Preconditions;

@Service
public class ExecutorContext {

  public ExecutorService executorService;
  private int DEFAULT_WAIT_SECONDS = 2;

  @PostConstruct
  public void init() {
    executorService = ExecutorManager.threadPoolExecutor;
  }

  public <T> List<T> waitAllFutures(List<Callable<T>> calls, int milliseconds) throws Exception {
    Preconditions.checkArgument(null != calls && !calls.isEmpty(), "callable empty.");
    LatchedCallables<T> latchAndCallables = wrapCallables(calls);
    List<Future<T>> futurres = new LinkedList<>();
    for (CountdownedCallable<T> callable : latchAndCallables.wrappedCallables) {
      if (null != callable) {
        futurres.add(executorService.submit(callable));
      }
    }
    List<T> rets = new ArrayList<>();
    if (latchAndCallables.latch.await(milliseconds, TimeUnit.MILLISECONDS)) {
      for (CountdownedCallable<T> call : latchAndCallables.wrappedCallables) {
        rets.add(call.getResult());
      }
    } else {
      for (Future<T> future : futurres) {
        if (!future.isDone()) {
          future.cancel(true);
        }
      }
    }
    return rets;
  }

  public <T> List<T> waitAllCallables(List<Callable<T>> calls, int seconds) throws Exception {
    Preconditions.checkArgument(null != calls && !calls.isEmpty(), "callable empty.");
    LatchedCallables<T> latchAndCallables = wrapCallables(calls);
    for (CountdownedCallable<T> callable : latchAndCallables.wrappedCallables) {
      executorService.submit(callable);
    }
    List<T> rets = new ArrayList<>();
    if (latchAndCallables.latch.await(seconds, TimeUnit.SECONDS)) {
      for (CountdownedCallable<T> call : latchAndCallables.wrappedCallables) {
        rets.add(call.getResult());
      }
    }
    return rets;
  }

  public <T> List<T> waitAllCallables(@SuppressWarnings("unchecked") Callable<T>... calls) throws Exception {
    Preconditions.checkNotNull(calls, "callable empty.");
    return waitAllCallables(Arrays.asList(calls), DEFAULT_WAIT_SECONDS);
  }

  private static <T> LatchedCallables<T> wrapCallables(List<Callable<T>> callables) {
    CountDownLatch latch = new CountDownLatch(callables.size());
    List<CountdownedCallable<T>> wrapped = new ArrayList<>(callables.size());
    for (Callable<T> callable : callables) {
      wrapped.add(new CountdownedCallable<>(callable, latch));
    }

    LatchedCallables<T> returnVal = new LatchedCallables<>();
    returnVal.latch = latch;
    returnVal.wrappedCallables = wrapped;
    return returnVal;
  }

  public static class LatchedCallables<T> {
    public CountDownLatch latch;
    public List<CountdownedCallable<T>> wrappedCallables;
  }

  public static class CountdownedCallable<T> implements Callable<T> {
    private final Callable<T> wrapped;
    private final CountDownLatch latch;
    private T result;

    public CountdownedCallable(Callable<T> wrapped, CountDownLatch latch) {
      this.wrapped = wrapped;
      this.latch = latch;
    }

    @Override
    public T call() throws Exception {
      try {
        result = wrapped.call();
        return result;
      } finally {
        latch.countDown();
      }
    }

    public T getResult() {
      return result;
    }
  }

}

4、创建一个测试类

package com.hao;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import com.hao.bean.Employee;
import com.hao.service.EmployeeService;
import com.hao.service.ExecutorContext;

public class ExecutorTest extends BaseTest {

  @Autowired
  ExecutorContext executorContext;
  
  @Autowired
  EmployeeService employeeService;

  @Test
  public void test01() {
    long t0 = System.currentTimeMillis();
    List<Employee> employees = new ArrayList<Employee>();
    try {
      List<Callable<Integer>> calls = new ArrayList<Callable<Integer>>();
      Callable<Integer> able1 = new Callable<Integer>() {
        @Override
        public Integer call() throws Exception {
          Thread.sleep(5000);
          Employee employee = employeeService.getById(1L);
          employees.add(employee);
          return 1;
        }

      };
      calls.add(able1);
      Callable<Integer> able2 = new Callable<Integer>() {
        @Override
        public Integer call() throws Exception {
          Thread.sleep(5000);
          Employee employee = employeeService.getById(2L);
          employees.add(employee);
          return 2;
        }

      };
      calls.add(able2);
      Callable<Integer> able3 = new Callable<Integer>() {
        @Override
        public Integer call() throws Exception {
          Thread.sleep(5000);
          Employee employee = employeeService.getById(3L);
          employees.add(employee);
          return 3;
        }

      };
      calls.add(able3);

      executorContext.waitAllCallables(calls, 5000);
    } catch (Exception e) {
      e.printStackTrace();
    }
    for (Employee employee : employees) {
      System.out.println(employee);
    }
    System.out.println(System.currentTimeMillis() - t0);
  }

}

5、执行结果如下

次工具类的好处在于能够像使用普通 service一样使用线程池完成并行操作,当然不要忘记将 ExecutorContext 置于能被sping扫描到的地方,

否则不能直接使用@Autowired 依赖注入

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 用Java实现24点游戏

    用Java实现24点游戏

    喜欢玩游戏的有福啦,文中有非常详细的开发框架,按着框架来实现就好啦.而且24点游戏是经典的纸牌益智游戏.,需要的朋友可以参考下
    2021-05-05
  • HashMap底层数据结构详细解析

    HashMap底层数据结构详细解析

    这篇文章主要介绍了HashMap底层数据结构详细解析,HashMap作为开发中常用的数据结构,也是面试中经常被问的知识点,因此作为开发者应该尽可能多的理解其底层的数据结构,需要的朋友可以参考下
    2023-11-11
  • SpringMvc+POI处理excel表数据导入

    SpringMvc+POI处理excel表数据导入

    这篇文章主要为大家详细介绍了SpringMvc+POI处理excel表数据导入,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-06-06
  • 详解JavaEE使用过滤器实现登录(用户自动登录 安全登录 取消自动登录黑用户禁止登录)

    详解JavaEE使用过滤器实现登录(用户自动登录 安全登录 取消自动登录黑用户禁止登录)

    主要介绍用户的自动登录和取消自动登录,以及实现一天自动登录或者n天实现自动登录,当用户ip被加入到黑名单之后,直接利用过滤器返回一个警告页面。接下来通过本文给大家介绍JavaEE使用过滤器实现登录的相关知识,感兴趣的朋友一起学习吧
    2016-05-05
  • Mybatis关联映射举例详解

    Mybatis关联映射举例详解

    关联关系是面向对象分析、面向对象设计最终的思想,Mybatis完全可以理解这种关联关系,如果关系得当,Mybatis的关联映射将可以大大简化持久层数据的访问
    2022-07-07
  • JAVA中Comparable接口和自定义比较器示例讲解

    JAVA中Comparable接口和自定义比较器示例讲解

    这篇文章主要给大家介绍了关于JAVA中Comparable接口和自定义比较器的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • SpringBoot实现联表查询的代码详解

    SpringBoot实现联表查询的代码详解

    这篇文章主要介绍了SpringBoot中如何实现联表查询,文中通过代码示例和图文结合的方式讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-05-05
  • Mybatis-Plus-AutoGenerator 最详细使用方法

    Mybatis-Plus-AutoGenerator 最详细使用方法

    这篇文章主要介绍了Mybatis-Plus-AutoGenerator 最详细使用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • 30分钟入门Java8之lambda表达式学习

    30分钟入门Java8之lambda表达式学习

    本篇文章主要介绍了30分钟入门Java8之lambda表达式学习,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04
  • Java常见的转义字符举例详解

    Java常见的转义字符举例详解

    在java字符常量中,反斜杠(\)是一个特殊的字符,被称为转义字符,它的作用是用来转义后面一个字符,这篇文章主要给大吉介绍了关于Java常见转义字符的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-02-02

最新评论