SpringBoot | 異步編程

  • @EnableAsync:通過在配置類或者Main類上加@EnableAsync開啓對異步方法的支持。

  • @Async 可以作用在類上或者方法上,作用在類上代表這個類的所有方法都是異步方法。

創建一個異步的任務配置類

package com.xiaobu.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 xiaobu
 * @version JDK1.8.0_171
 * @date on  2019/10/10 16:38
 * @description 異步任務配置類
 */
@Configuration
@EnableAsync
public class AsyncConfig {
    private static final int CORE_POOL_SIZE = 6;
    private static final int MAX_POOL_SIZE = 10;
    private static final int QUEUE_CAPACITY = 100;


    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(CORE_POOL_SIZE);
        threadPoolTaskExecutor.setMaxPoolSize(MAX_POOL_SIZE);
        threadPoolTaskExecutor.setQueueCapacity(QUEUE_CAPACITY);
        // 當最大池已滿時,此策略保證不會丟失任務請求,但是可能會影響應用程序整體性能。
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        threadPoolTaskExecutor.setThreadNamePrefix("My ThreadPoolTaskExecutor-");
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }

}

CompletableFuture.completedFuture(results) 完成之後再返回結果

package com.xiaobu.service;

import com.xiaobu.mapper.AreaMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author xiaobu
 * @version JDK1.8.0_171
 * @date on  2019/10/10
 * @description V1.0
 */
@Service
@Slf4j
public class AsyncService {

    private List<String> movies = Arrays.asList("AAA", "BBB", "CCC", "DDD", "EEE", "FFF");


    @Async
    public CompletableFuture<List<String>>  ompletableFutureTask(String start){
        log.info("[{}] start task",Thread.currentThread().getName());
        List<String> result=movies.stream().filter(movie->movie.startsWith(start)).collect(Collectors.toList());
        try {
            //模擬執行時間
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();

        }
        //返回一個已經用給定值完成的新的CompletableFuture。
        return CompletableFuture.completedFuture(result);
    }


    public static void main(String[] args) {
        AsyncService service = new AsyncService();
        service.ompletableFutureTask("A");
        List<String> words = Arrays.asList("A", "B");
        List<CompletableFuture<List<String>>> completableFutureList = words.stream().map(service::ompletableFutureTask).collect(Collectors.toList());
        System.out.println("completableFutureList = " + completableFutureList);
    }
}


編寫異步方法

package com.xiaobu.controller;

import com.xiaobu.base.utils.CmdUtils;
import com.xiaobu.service.AsyncService;
import org.springframework.util.StopWatch;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author xiaobu
 * @version JDK1.8.0_171
 * @date on  2019/8/23 13:40
 * @description
 */
@RestController
@RequestMapping("async")
public class AsyncController {

    @Resource
    private AsyncService asyncService;

    @GetMapping("movie")
    public String movies() {
        long startTime = System.currentTimeMillis();
        StopWatch stopWatch = new StopWatch();
        stopWatch.start("movie任務");
        List<String> words = Arrays.asList("A", "B","C","D","E","F");
        List<CompletableFuture<List<String>>> completableFutureList = words.stream().map(word -> asyncService.ompletableFutureTask(word)).collect(Collectors.toList());
        List<List<String>> results = completableFutureList.stream().map(CompletableFuture::join).collect(Collectors.toList());
        stopWatch.stop();
        System.out.println("stopWatch = " + stopWatch.prettyPrint());
        System.out.println("耗時:"+(System.currentTimeMillis() - startTime));
        return results.toString();
    }
}

結果如下:

1570846891.jpg

可以看出執行任務花費了1秒鐘的時間,6個線程異步執行的。下面將核心線程池大小改成2之後,查看下執行結果。

1570847953(1).jpg

改造下service和controller類 業務層設置無返回值

 @Async
    public void ompletableFutureTask(String start){
        log.info("[{}] start task",Thread.currentThread().getName());
        List<String> result=movies.stream().filter(movie->movie.startsWith(start)).collect(Collectors.toList());
        try {
            //模擬執行時間
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();

        }
        //返回一個已經用給定值完成的新的CompletableFuture。
        System.out.println("result = " + result);
    }
@GetMapping("movie")
    public String movies() {
        long startTime = System.currentTimeMillis();
        StopWatch stopWatch = new StopWatch();
        stopWatch.start("movie任務");
        List<String> words = Arrays.asList("A", "B","C","D","E","F");
       words.stream().forEach(word -> asyncService.ompletableFutureTask(word));
        stopWatch.stop();
        System.out.println("stopWatch = " + stopWatch.prettyPrint());
        System.out.println("耗時:"+(System.currentTimeMillis() - startTime));
        return "success";
    }

1570848992.jpg

結果:先返回結果,然後系統再執行。

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