美文网首页
spring boot 异步实现@Async

spring boot 异步实现@Async

作者: 5eac0cfdd510 | 来源:发表于2019-07-09 21:28 被阅读0次

    一、异步与同步

    • 异步调用:程序在顺序执行时,不等待异步调用的语句返回结果就执行后面的程序;
    • 同步调用:程序按照定义顺序依次执行,每行代码必须等待上一行程序执行完才能执行;
      下面我们通过代码详细比较同步与异步的差异

    同步调用

    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Component;
    
    import java.util.Random;
    
    /**
     * 同步信息
     *
     * @author <a href="jian.huang@bintools.cn">yunzhe</a>
     * @version 1.0.0 2019-07-09-下午8:45
     */
    @Component
    @Slf4j
    public class SyncTask {
        public static Random random = new Random();
        public void doTaskOne() throws InterruptedException {
            log.info("sync开始任务一");
            long start = System.currentTimeMillis();
            Thread.sleep(random.nextInt(10000));
            long end = System.currentTimeMillis();
            log.info("sync完成任务一、耗时:"+(end-start)+"毫秒");
        }
        public void doTaskTwo() throws InterruptedException {
            log.info("sync开始任务二");
            long start = System.currentTimeMillis();
            Thread.sleep(random.nextInt(10000));
            long end = System.currentTimeMillis();
            log.info("sync完成任务二、耗时:"+(end-start)+"毫秒");
        }
        public void doTaskThree() throws InterruptedException {
            log.info("sync开始任务三");
            long start = System.currentTimeMillis();
            Thread.sleep(random.nextInt(10000));
            long end = System.currentTimeMillis();
            log.info("sync完成任务三、耗时:"+(end-start)+"毫秒");
        }
    }  
    

    执行结果;

    syncTask.jpg

    异步处理

    • 1 创建连接池
    /***
         * 创建线程池
         */
        @EnableAsync
        @Configuration
        class TaskPoolConfig{
            @Bean("taskExecutor")
            public Executor taskExecutor(){
                ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
                executor.setCorePoolSize(10);
                executor.setMaxPoolSize(20);
                executor.setQueueCapacity(200);
                executor.setKeepAliveSeconds(60);
                executor.setThreadNamePrefix("taskExecutor-");
                executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
                return executor;
            }
        }
    
    • 2 异步处理
    import java.util.Random;
    
    /**
    * 异步处理
    *
    * @author <a href="jian.huang@bintools.cn">yunzhe</a>
    * @version 1.0.0 2019-07-09-上午11:19
    */
    @Slf4j
    @Component
    public class Task {
       public static Random random = new Random();
       @Async("taskExecutor")
       public void doTaskOne() throws InterruptedException {
           log.info("开始任务一");
           long start = System.currentTimeMillis();
           Thread.sleep(random.nextInt(10000));
           long end = System.currentTimeMillis();
           log.info("完成任务一、耗时:"+(end-start)+"毫秒");
       }
       @Async("taskExecutor")
       public void doTaskTwo() throws InterruptedException {
           log.info("开始任务二");
           long start = System.currentTimeMillis();
           Thread.sleep(random.nextInt(10000));
           long end = System.currentTimeMillis();
           log.info("完成任务二、耗时:"+(end-start)+"毫秒");
       }
       @Async("taskExecutor")
       public void doTaskThree() throws InterruptedException {
           log.info("开始任务三");
           long start = System.currentTimeMillis();
           Thread.sleep(random.nextInt(10000));
           long end = System.currentTimeMillis();
           log.info("完成任务三、耗时:"+(end-start)+"毫秒");
       }
    }    
    
    • 3 执行结果


      task.jpg

    异步回调

    有时我们需要对异步调用的结果进行相关的处理,此时需要进行相应的回掉。具体操作如下:

    /***
    *
    */
    @Component
    @Slf4j
    public class AsyncTask {
        @Async("taskExecutor")
        public Future<String> doTask() throws InterruptedException {
            log.info("Task1 started");
            long start = System.currentTimeMillis();
            Thread.sleep(5000);
            long end = System.currentTimeMillis();
            log.info("Task1 finished,time elapsed:{} ms",end-start);
            return new AsyncResult<>("Task1 accomplished");
        }
        @Async("taskExecutor")
        public Future<String> doTask2() throws InterruptedException {
            log.info("Task2 started");
            long start = System.currentTimeMillis();
            Thread.sleep(3000);
            long end = System.currentTimeMillis();
            log.info("Task2 finished,time elapsed:{} ms",end-start);
            return new AsyncResult<>("Task2 accomplished");
        }
    }  
    

    异步回调结果在单元测试的主类中

    单元测试

    package com.example.springbootasync;
    
    import com.example.springbootasync.sync.SyncTask;
    import lombok.extern.slf4j.Slf4j;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.Future;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    @Slf4j
    public class SpringbootasyncApplicationTests {
    
        @Autowired
        private Task task;
    
        @Autowired
        private AsyncTask asyncTask;
        @Autowired
        private SyncTask syncTask;
        @Test
        public void syncTaskTest() throws InterruptedException {
            syncTask.doTaskOne();
            syncTask.doTaskTwo();
            syncTask.doTaskThree();
    
        }
        @Test
        public void contextLoads() throws InterruptedException {
            task.doTaskOne();
            task.doTaskTwo();
            task.doTaskThree();
            Thread.currentThread().join();
        }
        @Test
        public void AsyncTaskTest() throws InterruptedException, ExecutionException {
            Future<String> task1 = asyncTask.doTask();
            Future<String> task2 = asyncTask.doTask2();
            while(true){
                if(task1.isDone() && task2.isDone()){
                    log.info("TASK1 result: {}",task1.get());
                    log.info("TASK2 result: {}",task2.get());
                    break;
                }
                Thread.sleep(1000);
            }
            log.info("All tasks finished.");
        }
    }
    

    总结

    通过以上操作,我们对同步与异步进行了一定的了解。通过代码对异步回调有初步的认识。但是在一些具体的业务场景中如何处理,需要进行相应的场景修改。
    码云地址:https://gitee.com/huangjian163/springbootSync.git

    相关文章

      网友评论

          本文标题:spring boot 异步实现@Async

          本文链接:https://www.haomeiwen.com/subject/ranfkctx.html