Java线程池应用之ScheduledThreadPoolExecutor(含示例代码)

ScheduledThreadPoolExecutor 继承自 ThreadPoolExecutor,它主要用来在给定的延迟之后运行任务,或者定期执行任务。

public ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue(), threadFactory);
    }

ScheduledThreadPoolExecutor 的功能与 Timer 类似,但功能更强大、更灵活。Timer 对应的是单个后台线程,而ScheduledThreadPoolExecutor 可以在构造函数中指定多个对应的后台线程数。
Java 提供了多种类型的 ScheduledThreadPoolExecutor ,可以通过 Executors 创建,比较常见的有 ScheduledThreadPool、SingleThreadScheduledExecutor 等。适用于需要多个后台线程执行周期任务,同时为了满足资源管理的需求而需要限制后台线程数量的应用场景。

	static ThreadFactory threadFactory = new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").build();
    static ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5, threadFactory);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 1. 延迟 3 秒后执行 Runnable 方法
        scheduledExecutorService.schedule(() -> System.out.println("Hello World"), 3000, TimeUnit.MILLISECONDS);

        // 2. 延迟 3 秒后执行 Callable 方法
        ScheduledFuture<String> scheduledFuture = scheduledExecutorService.schedule(() -> "Hello ScheduledFuture", 3000, TimeUnit.MILLISECONDS);
        System.out.println(scheduledFuture.get());

        // 3. 延迟 1 秒后开始每隔 3 秒周期执行。
        //    如果中间任务遇到异常,则禁止后续执行。
        //    固定的频率来执行某项任务,它不受任务执行时间的影响。到时间,就执行。
        scheduledExecutorService.scheduleAtFixedRate(() -> System.out.println("Hello ScheduleAtFixedRate"), 1, 3000, TimeUnit.MILLISECONDS);

        // 4. 延迟 1 秒后,每个任务结束延迟 3 秒后再执行下个任务。
        //    如果中间任务遇到异常,则禁止后续执行。
        //    受任务执行时间的影响,等待任务执行结束后才开始计算延迟。
        scheduledExecutorService.scheduleWithFixedDelay(() -> System.out.println("Hello ScheduleWithFixedDelay"), 1, 3000, TimeUnit.MILLISECONDS);
    }

ScheduledThreadPoolExecutor 的执行步骤大抵如下:
1.当调用 ScheduledThreadPoolExecutor 的 scheduleAtFixedRate() 方法或者 scheduleWithFixedDelay()方 法时,会向 DelayedWorkQueue 队列添加 ScheduledFutureTask 任务;
2.线程池中的线程从 DelayedWorkQueue队列中获取执行时间已到达的 ScheduledFutureTask,然后执行任务;
3.线程修改 ScheduledFutureTask 任务的执行时间为下次将要被执行的时间;
4.线程把修改后的 ScheduledFutureTask 重新放回队列。

在实际应用中,可将ScheduledThreadPoolExecutor用于服务端异步解决HTTP请求,避免高并发导致阻塞。示例代码如下:

	private static final Logger logger = LoggerFactory.getLogger(PhoneController.class);
    private static ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1000,
            new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());

	@RequestMapping(value = "/getData")
    public HttpResult getData(@RequestBody CheckResultParam param) {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                if (null != param && null != param.getData()) {
                    logger.info("Total Data Count: " + param.getData().size());
                    for (CheckDataParam data : param.getData()) {
                        logger.info("Data: " + JSON.toJSONString(data));
                    }
                }
            }
        });
        HttpResult result = new HttpResult("200", "Test", null);
        logger.info("Test getData");
        return result;
    }

注:使用BasicThreadFactory类需要引入org.apache.commons.lang3.concurrent.BasicThreadFactory

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章