Skip to content

Latest commit

 

History

History
186 lines (156 loc) · 6.71 KB

HELP.md

File metadata and controls

186 lines (156 loc) · 6.71 KB

spring-boot-async

使用场景

  1. 在用户注册通过的同时给用户发短信。

在用户注册的这个接口中,发送短信的逻辑是否应该占用用户注册的时间?

  1. 批量推送消息给用户。

当用户量很大时,如何快速推送?

  1. 凌晨系统自动化统计数据。

当统计的数据量很大,统计的指标很多,如何加快定时器统计效率?

演示异步编程

配置类

  • @EnableAsync注解可以直接放在SpringBoot启动类上,也可以单独放在其他配置类上
@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {
    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();
        //设置核心线程数
        threadPool.setCorePoolSize(10);
        //设置最大线程数
        threadPool.setMaxPoolSize(100);
        //线程池所使用的缓冲队列
        threadPool.setQueueCapacity(10);
        // 拒绝策略, 由当前执行线程执行
        threadPool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //等待任务在关机时完成--表明等待所有线程执行完
        threadPool.setWaitForTasksToCompleteOnShutdown(true);
        // 等待时间 (默认为0,此时立即停止),并没等待xx秒后强制停止
        threadPool.setAwaitTerminationSeconds(60);
        //  线程名称前缀
        threadPool.setThreadNamePrefix("async-");
        // 初始化线程
        threadPool.initialize();
        return threadPool;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return null;
    }
}

方法标记 @Async注解

@Component
@Slf4j
public class AsyncJob {

    @Async
    public void job() throws InterruptedException {
        doTask("job", 1);
    }

    /**
     * 模拟5秒的异步任务
     */
    @Async
    public Future<Boolean> job1() throws InterruptedException {
        doTask("job1", 5);
        return new AsyncResult<>(Boolean.TRUE);
    }

    /**
     * 模拟2秒的异步任务
     */
    @Async
    public Future<Boolean> job2() throws InterruptedException {
        doTask("job2", 2);
        return new AsyncResult<>(Boolean.TRUE);
    }

    /**
     * 模拟3秒的异步任务
     */
    @Async
    public Future<Boolean> job3() throws InterruptedException {
        doTask("job3", 3);
        return new AsyncResult<>(Boolean.TRUE);
    }

    /**
     * 模拟5秒的同步任务
     */
    public void task1() throws InterruptedException {
        doTask("task1", 5);
    }

    /**
     * 模拟2秒的同步任务
     */
    public void task2() throws InterruptedException {
        doTask("task2", 2);
    }

    /**
     * 模拟3秒的同步任务
     */
    public void task3() throws InterruptedException {
        doTask("task3", 3);
    }

    private void doTask(String taskName, Integer time) throws InterruptedException {
        Long startTime = System.currentTimeMillis();
        log.info("{}开始执行,当前线程名称【{}】", taskName, Thread.currentThread().getName());
        TimeUnit.SECONDS.sleep(time);
        log.info("{}执行成功,当前线程名称【{}】耗时 {} ms", taskName, Thread.currentThread().getName(), System.currentTimeMillis() - startTime);
    }
}

单元测试

    @Autowired
    private AsyncJob asyncJob;

    /**
     * 测试异步任务
     */
    @Test
    public void asyncTaskTest() throws InterruptedException, ExecutionException {
        long startTime = System.currentTimeMillis();
        Future<Boolean> asyncTask1 = asyncJob.job1();
        Future<Boolean> asyncTask2 = asyncJob.job2();
        Future<Boolean> asyncTask3 = asyncJob.job3();

        // 获取异步任务的处理结果,异步任务没有处理完成,会一直阻塞,可以设置超时时间,使用 get 的重载方法
        asyncTask1.get();
        asyncTask2.get();
        asyncTask3.get();
        long endTime = System.currentTimeMillis();

        log.info("异步任务,总耗时:{} 毫秒", (endTime - startTime));

    }


    /**
     * 测试同步任务
     */
    @Test
    public void taskTest() throws InterruptedException {
        long startTime = System.currentTimeMillis();

        asyncJob.task1();
        asyncJob.task2();
        asyncJob.task3();
        long endTime = System.currentTimeMillis();

        log.info("同步任务,总耗时:{} 毫秒", (endTime - startTime));
    }

运行结果

异步结果

2022-04-18 16:57:36.729  INFO 62093 --- [        async-2] com.example.job.AsyncJob                 : job2开始执行当前线程名称async-22022-04-18 16:57:36.729  INFO 62093 --- [        async-3] com.example.job.AsyncJob                 : job3开始执行当前线程名称async-32022-04-18 16:57:36.729  INFO 62093 --- [        async-1] com.example.job.AsyncJob                 : job1开始执行当前线程名称async-12022-04-18 16:57:38.736  INFO 62093 --- [        async-2] com.example.job.AsyncJob                 : job2执行成功当前线程名称async-2耗时 2007 ms
2022-04-18 16:57:39.733  INFO 62093 --- [        async-3] com.example.job.AsyncJob                 : job3执行成功当前线程名称async-3耗时 3004 ms
2022-04-18 16:57:41.736  INFO 62093 --- [        async-1] com.example.job.AsyncJob                 : job1执行成功当前线程名称async-1耗时 5007 ms
2022-04-18 16:57:41.736  INFO 62093 --- [           main] c.e.SpringBootAsyncApplicationTests      : 异步任务总耗时5015 毫秒

同步结果

2022-04-18 17:14:44.911  INFO 62613 --- [           main] com.example.job.AsyncJob                 : task1开始执行当前线程名称main2022-04-18 17:14:49.916  INFO 62613 --- [           main] com.example.job.AsyncJob                 : task1执行成功当前线程名称main耗时 5005 ms
2022-04-18 17:14:49.917  INFO 62613 --- [           main] com.example.job.AsyncJob                 : task2开始执行当前线程名称main2022-04-18 17:14:51.922  INFO 62613 --- [           main] com.example.job.AsyncJob                 : task2执行成功当前线程名称main耗时 2005 ms
2022-04-18 17:14:51.923  INFO 62613 --- [           main] com.example.job.AsyncJob                 : task3开始执行当前线程名称main2022-04-18 17:14:54.928  INFO 62613 --- [           main] com.example.job.AsyncJob                 : task3执行成功当前线程名称main耗时 3005 ms
2022-04-18 17:14:54.928  INFO 62613 --- [           main] c.e.SpringBootAsyncApplicationTests      : 同步任务总耗时10022 毫秒