【工具类】实现自定义线程池
概要:
1.基于spring-context实现
2.基于JDK1.8实现
方案一.使用org.springframework:spring-context:5.1.2.RELEASE:定义线程池
第一步,先在配置类中定义一个线程池,比如:
package com.songzhen.howcool.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor; /** * 自定义线程池配置类 * * @author Lucas * @version 1.0 * @date 2018/10/15 17:51 **/ @EnableAsync @Configuration public class TaskPoolConfig { @Bean("taskExecutor") public Executor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); executor.setMaxPoolSize(32); executor.setQueueCapacity(200); executor.setKeepAliveSeconds(60); executor.setThreadNamePrefix("taskExecutor-"); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); return executor; } }
上面我们通过使用ThreadPoolTaskExecutor创建了一个线程池,同时设置了以下这些参数:
- 核心线程数10:线程池创建时候初始化的线程数
- 最大线程数32:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
- 缓冲队列200:用来缓冲执行任务的队列
- 允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
- 线程池名的前缀taskExecutor-:设置好了之后可以方便我们定位处理任务所在的线程池
- 线程池对拒绝任务的处理策略:这里采用了
CallerRunsPolicy策略,当线程池没有处理能力的时候,该策略会直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务
使用线程池
第二步,在定义了线程池之后,我们如何让异步调用的执行任务使用这个线程池中的资源来运行呢?方法非常简单,我们只需要在@Async注解中指定线程池名即可,比如:
package com.songzhen.howcool.biz; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; /** * 异步调用自定义线程池处理任务 * * @author Lucas * @version 1.0 * @date 2018/10/15 17:51 **/ @Component public class Task { private static final Logger logger = LoggerFactory.getLogger(Task.class); @Async("taskExecutor") public void doTask() { logger.info("开始做任务"); long start = System.currentTimeMillis(); try { Thread.sleep(1000); } catch (InterruptedException e) { logger.error("Have a interruptedException {}", e); Thread.currentThread().interrupt(); } long end = System.currentTimeMillis(); logger.info("完成任务,耗时:{} 毫秒", end - start); } }
方案二.使用JDK本身java.util.concurrent包里自带Util:定义线程池
private static final ThreadFactory THREAD_FACTORY = new ThreadFactoryBuilder().setNameFormat("taskExecutor-pool-%d").build(); private static final ExecutorService EXECUTOR = new ThreadPoolExecutor(1, 3, 120, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1024), THREAD_FACTORY, new ThreadPoolExecutor.AbortPolicy()); /** * 处理业务 * * @date 16:10 2019/4/10 */ public void handlerBusiness { EXECUTOR .execute(()-> sendMessage(mobile, context)); EXECUTOR .shutdown(); … } /** * 发送短信 * * @date 16:11 2019/4/10 */ public void sendMessage(String mobile, String context) { System.out.println(Thread.currentThread().getName())); int remainingTimes = 3; try { do { // TODO调用短信平台发送短信 remainingTimes--; Thread.sleep(20000); } while (remainingTimes <= 3); } catch (InterruptedException e) { System.out.println("Thread have a interruptedException"); // 只对阻塞线程起作用,当线程阻塞时退出线程,对于正在运行的线程,没有任何作用! Thread.currentThread().interrupt(); } }
private void getAddress() throws Exception { // 创建线程池 ExecutorService pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 16 + 2); BlockingQueue<Future<String>> queue = new LinkedBlockingQueue<>(); // 扔任务 for (int i = 0; i < 10; i++) { Future<String> future = pool.submit(new TaskGMapThread(0, 0)); queue.add(future); } // 检查线程池任务执行结果 for (int i = 0; i < 10; i++) { String address = queue.take().get(); } // 关闭线程池 pool.shutdown(); } class TaskGMapThread implements Callable<String> { private double latitude; private double longitude; public TaskGMapThread(double latitude, double longitude) { this.latitude = latitude; this.longitude = longitude; } @Override public String call() throws Exception { return "key"+latitude+latitude; } }
天不酬勤不够勤,勤到极处自酬人。 ---持续学习

浙公网安备 33010602011771号