最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

springboot?@Async?注解如何實(shí)現(xiàn)方法異步

 更新時(shí)間:2021年11月20日 17:10:42   作者:Bug布道師  
這篇文章主要介紹了springboot?@Async?注解如何實(shí)現(xiàn)方法異步,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

@Async注解如何實(shí)現(xiàn)方法異步

處理大批量數(shù)據(jù)的時(shí)候,效率很慢。所以考慮一下使用多線程。

剛開始自己手寫的一套,用了線程池啟動(dòng)固定的線程數(shù)進(jìn)行跑批。但是后來老大考慮到自己手寫的風(fēng)險(xiǎn)不好控制,所以使用spring的方法。

這里沒有詳細(xì)介紹,只有簡(jiǎn)單的demo,只會(huì)用,不懂原理:

一、springboot的App類需要的注解

package com.xxx.xxx.xxx;
import java.util.concurrent.ThreadPoolExecutor;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
/**
 * 類功能說明:服務(wù)生產(chǎn)者啟動(dòng)類
 * <p>
 * <strong></strong>
 * </p>
 *
 * @version
 * @author
 * @since 1.8
 */
@Configuration
@EnableAsync
public class Application extends SpringBootServletInitializer { 
    @Bean
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 設(shè)置核心線程數(shù)
        executor.setCorePoolSize(5);
        // 設(shè)置最大線程數(shù)
        executor.setMaxPoolSize(60);
        // 設(shè)置隊(duì)列容量
        executor.setQueueCapacity(20);
        // 設(shè)置線程活躍時(shí)間(秒)
        executor.setKeepAliveSeconds(60);
        // 設(shè)置默認(rèn)線程名稱
        executor.setThreadNamePrefix("what-");
        // 設(shè)置拒絕策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任務(wù)結(jié)束后再關(guān)閉線程池
        executor.setWaitForTasksToCompleteOnShutdown(true);        
        return executor;
    }    
}

springboot的App類,很簡(jiǎn)單,就能使用很多東西。

二、service層的注解

package com.xxx.xxx.service.impl; 
import java.util.concurrent.Future; 
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service; 
import com.xxx.xxx.service.XXXAsyncService ;
 
@Service
public class XXXAsyncServiceImpl implements XXXAsyncService { 
    @Async
    public Future<Long> rtn1() throws Exception {
        //do something
        //有返回值的時(shí)候,可以返回string,long之類的。
        return new AsyncResult<>(1);
    } 
    @Async
    public void rtn2() throws Exception {
        //do something
        //這個(gè)可以沒有返回值.
    }
}

三、調(diào)用層

package com.xxx.xxx.controller; 
import java.util.concurrent.Future; 
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController; 
import com.xxx.xxx.service.XXXAsyncService;
 
@RestController
@RequestMapping(value="/xxx") 
public class XXXAsyncController { 
 @Autowired
 private XXXAsyncService xxxAsyncService; 
 /**
  * 這里調(diào)用異步方法
  */
    @RequestMapping(value = "/xxx")
 public void dodo() throws Exception {     
  int threads = 10;//十個(gè)線程
        List<Future<Long>> list = new ArrayList<>();
        for(int i = 0;i < threads; i++){
         //這里循環(huán)調(diào)用異步方法。
      //如果存在大量數(shù)據(jù),可以在這里把數(shù)據(jù)切片,然后循環(huán)調(diào)用,分批處理數(shù)據(jù)。效率杠杠的。
   list .add(xxxAsyncService.rtn1());
        }
        long count = 0;
        for(Future<Long> l : tsfCountList) {
         //異步調(diào)用需要返回值的時(shí)候,這里可以把返回值都放入到list集合中,然后可以統(tǒng)一處理。 這里的get()是阻塞的,因?yàn)樾枰援惒椒椒ǚ祷?,在繼續(xù)執(zhí)行。
         count += l.get();
        }
        System.out.println("調(diào)用次數(shù):" + count);
 }
}

這些代碼全是手寫,記錄下來,以后用的時(shí)候,省的忘了,查起來麻煩。。

異步注解@Async的使用以及注意事項(xiàng)

第一步開啟異步

@Configuration
@EnableAsync
public class SpringAsyncConfig { ... }

默認(rèn)情況下,@EnableAsync檢測(cè)Spring的@Async注釋和EJB 3.1 javax. EJB .異步;此選項(xiàng)還可用于檢測(cè)其他用戶定義的注釋類型。(也可以在SpringBoot的啟動(dòng)類上直接加@EnableAsync注解)

在 Spring 中,用 @Async 注解指定的方法,該方法被調(diào)用時(shí)會(huì)以異步的方式執(zhí)行。而如果沒有在 @Async 注解中指定線程池,就會(huì)使用默認(rèn)的線程池。默認(rèn)的線程池為 SimpleAsyncTaskExecutor 。

該線程池不會(huì)復(fù)用線程,每有一個(gè)新任務(wù)被提交,該線程池就會(huì)創(chuàng)建一個(gè)新的線程實(shí)例用于執(zhí)行任務(wù)。下面為相關(guān)的代碼:

protected void doExecute(Runnable task) {
    Thread thread = (this.threadFactory != null ? this.threadFactory.newThread(task) : createThread(task));
    thread.start();
}

而如果想要指定線程池,可以通過在 @Async 注解中的 value 參數(shù)中指定所要使用的線程池的 Bean Name 。另一種方法是是一個(gè)實(shí)現(xiàn)了 AsyncConfigurer 接口或是繼承其默認(rèn)適配器類 AsyncConfigurerSupport 的配置類,這樣 @Async 注解的方法就會(huì)使用指定的自定義的線程池。

使用@Async注解的話采用的是springBoot默認(rèn)的線程池,不過一般我們會(huì)自定義線程池(因?yàn)楸容^靈活),配置方式有:

  • 使用 xml 文件配置的方式
  • 使用Java代碼結(jié)合@Configuration進(jìn)行配置(推薦使用)

下面顯示配置線程的代碼實(shí)現(xiàn)

package com.deppon.ptos.load.config; 
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
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;
 
/**
 * @Description: 異步線程管理
 * @Author:   LYH
 * @CreateDate: 2019/6/27 8:54
 * @Version: 1.0
 * @JDK: 1.8
 */
@Configuration
@EnableAsync
@Slf4j
public class ExecutorConfig {  
    @Value("${async.executor.thread.core_pool_size}")
    private int corePoolSize;
    @Value("${async.executor.thread.max_pool_size}")
    private int maxPoolSize;
    @Value("${async.executor.thread.queue_capacity}")
    private int queueCapacity;
    @Value("${async.executor.thread.name.prefix}")
    private String namePrefix;
 
    @Bean(name = "asyncServiceExecutor")
    public Executor asyncServiceExecutor() {
        log.info("start asyncServiceExecutor");
        ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor();
        //配置核心線程數(shù)
        executor.setCorePoolSize(corePoolSize);
        //配置最大線程數(shù)
        executor.setMaxPoolSize(maxPoolSize);
        //配置隊(duì)列大小
        executor.setQueueCapacity(queueCapacity);
        //配置線程池中的線程的名稱前綴
        executor.setThreadNamePrefix(namePrefix);
 
        // rejection-policy:當(dāng)pool已經(jīng)達(dá)到max size的時(shí)候,如何處理新任務(wù)
        // CALLER_RUNS:不在新線程中執(zhí)行任務(wù),而是有調(diào)用者所在的線程來執(zhí)行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //執(zhí)行初始化
        executor.initialize();
        return executor;
    }
}
package com.deppon.ptos.load.config;  
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.util.concurrent.ListenableFuture; 
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
 
/**
 * @Description: 打印異步線程的執(zhí)行情況   使用Callbale Future 來返回線程的信息
 * @Author: 633805  LYH
 * @CreateDate: 2019/6/27 8:59
 * @Version: 1.0
 * @JDK: 1.8
 */
@Component
@Slf4j
public class VisiableThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {  
    private void showThreadPoolInfo(String prefix) {
        ThreadPoolExecutor threadPoolExecutor = getThreadPoolExecutor(); 
        if (null == threadPoolExecutor) {
            return;
        }
 
        log.info("{}, {},taskCount [{}], completedTaskCount [{}], activeCount [{}], queueSize [{}]",
                this.getThreadNamePrefix(),
                prefix,
                threadPoolExecutor.getTaskCount(),
                threadPoolExecutor.getCompletedTaskCount(),
                threadPoolExecutor.getActiveCount(),
                threadPoolExecutor.getQueue().size());
    }
 
    @Override
    public void execute(Runnable task) {
        showThreadPoolInfo("1. do execute");
        super.execute(task);
    }
 
    @Override
    public void execute(Runnable task, long startTimeout) {
        showThreadPoolInfo("2. do execute");
        super.execute(task, startTimeout);
    }
 
    @Override
    public Future<?> submit(Runnable task) {
        showThreadPoolInfo("1. do submit");
        return super.submit(task);
    }
 
    @Override
    public <T> Future<T> submit(Callable<T> task) {
        showThreadPoolInfo("2. do submit");
        return super.submit(task);
    }
 
    @Override
    public ListenableFuture<?> submitListenable(Runnable task) {
        showThreadPoolInfo("1. do submitListenable");
        return super.submitListenable(task);
    }
 
    @Override
    public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
        showThreadPoolInfo("2. do submitListenable");
        return super.submitListenable(task);
    }
}

使用:

@Async("asyncServiceExecutor")

到這一步,異步就算開啟了。

下面主要說一說錯(cuò)誤的

使用@Async導(dǎo)致異步不成功的情況

如下方式會(huì)使@Async失效

  • 異步方法使用static修飾
  • 異步類沒有使用@Component注解(或其他注解)導(dǎo)致spring無法掃描到異步類
  • 異步方法不能與被調(diào)用的異步方法在同一個(gè)類中
  • 類中需要使用@Autowired或@Resource等注解自動(dòng)注入,不能自己手動(dòng)new對(duì)象
  • 如果使用SpringBoot框架必須在啟動(dòng)類中增加@EnableAsync注解

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java 通過 二三法 巧解前端數(shù)據(jù)顯示

    Java 通過 二三法 巧解前端數(shù)據(jù)顯示

    實(shí)踐來源于理論,做開發(fā)前肯定要先了解相關(guān)的規(guī)則和原理,看到標(biāo)題或許你會(huì)好奇什么是二三法。本篇文章帶你深入了解,需要的朋友可以參考下
    2021-10-10
  • Java?協(xié)程?Quasar詳解

    Java?協(xié)程?Quasar詳解

    這篇文章主要介紹了Java?協(xié)程?Quasar詳解,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-07-07
  • springboot的控制反轉(zhuǎn)和自動(dòng)裝配示例代碼

    springboot的控制反轉(zhuǎn)和自動(dòng)裝配示例代碼

    這篇文章主要介紹了springboot的控制反轉(zhuǎn)和自動(dòng)裝配的相關(guān)知識(shí),本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-06-06
  • SpringCloud-Alibaba-Nacos啟動(dòng)失敗解決方案

    SpringCloud-Alibaba-Nacos啟動(dòng)失敗解決方案

    這篇文章主要介紹了SpringCloud-Alibaba-Nacos啟動(dòng)失敗解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • mybatis 一對(duì)一、一對(duì)多和多對(duì)多查詢實(shí)例代碼

    mybatis 一對(duì)一、一對(duì)多和多對(duì)多查詢實(shí)例代碼

    這篇文章主要介紹了mybatis 一對(duì)一、一對(duì)多和多對(duì)多查詢的實(shí)例代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-06-06
  • SpringBoot請(qǐng)求參數(shù)加密、響應(yīng)參數(shù)解密的實(shí)現(xiàn)

    SpringBoot請(qǐng)求參數(shù)加密、響應(yīng)參數(shù)解密的實(shí)現(xiàn)

    在項(xiàng)目開發(fā)工程中,有的項(xiàng)目可能對(duì)參數(shù)安全要求比較高,在整個(gè)http數(shù)據(jù)傳輸?shù)倪^程中都需要對(duì)請(qǐng)求參數(shù)、響應(yīng)參數(shù)進(jìn)行加密,本文主要介紹了SpringBoot請(qǐng)求參數(shù)加密、響應(yīng)參數(shù)解密的實(shí)現(xiàn),感興趣的可以了解一下
    2024-01-01
  • 使用Java8實(shí)現(xiàn)觀察者模式的方法(上)

    使用Java8實(shí)現(xiàn)觀察者模式的方法(上)

    本文給大家介紹使用java8實(shí)現(xiàn)觀察者模式的方法,涉及到j(luò)ava8觀察者模式相關(guān)知識(shí),對(duì)此感興趣的朋友一起學(xué)習(xí)吧
    2016-02-02
  • 解決poi導(dǎo)出時(shí)單元格樣式被覆蓋問題

    解決poi導(dǎo)出時(shí)單元格樣式被覆蓋問題

    這篇文章主要介紹了解決poi導(dǎo)出時(shí)單元格樣式被覆蓋問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Springboot使用ResponseBody漢字返回問號(hào)問題

    Springboot使用ResponseBody漢字返回問號(hào)問題

    這篇文章主要介紹了Springboot使用ResponseBody漢字返回問號(hào)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • Spring接口ApplicationRunner用法詳解

    Spring接口ApplicationRunner用法詳解

    這篇文章主要介紹了Spring接口ApplicationRunner的作用和使用介紹,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-08-08

最新評(píng)論

台东县| 库尔勒市| 广德县| 怀来县| 耿马| 桓台县| 灵台县| 汾西县| 阜平县| 吉隆县| 微博| 柘城县| 哈尔滨市| 崇阳县| 五家渠市| 佛学| 交口县| 双桥区| 买车| 化德县| 荆州市| 张北县| 长垣县| 玛多县| 敦化市| 铁岭市| 磴口县| 天峻县| 年辖:市辖区| 凤凰县| 许昌县| 益阳市| 梁平县| 虞城县| 翁牛特旗| 辉南县| 山阳县| 松溪县| 栾城县| 茶陵县| 阜新|