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

詳解java開啟異步線程的幾種方法(@Async,AsyncManager,線程池)

 更新時間:2023年09月18日 11:11:05   作者:天河歸來  
在springboot框架中,可以使用注解簡單實現(xiàn)線程的操作,還有AsyncManager的方式,如果需要復(fù)雜的線程操作,可以使用線程池實現(xiàn),本文通過實例代碼介紹java開啟異步線程的幾種方法(@Async,AsyncManager,線程池),感興趣的朋友一起看看吧

整體描述

在java中異步線程很重要,比如在業(yè)務(wù)流處理時,需要通知硬件設(shè)備,發(fā)短信通知用戶,或者需要上傳一些圖片資源到其他服務(wù)器這種耗時的操作,在主線程里處理會阻塞整理流程,而且我們也不需要等待處理結(jié)果之后再進(jìn)行下一步操作,這時候就可以使用異步線程進(jìn)行處理,這樣主線程不會因為這些耗時的操作而阻塞,保證主線程的流程可以正常進(jìn)行。最近在項目中使用了很多線程的操作,在這做個記錄。

實現(xiàn)方法

線程的操作,是java中最重要的部分之一,實現(xiàn)線程操作也有很多種方法,這里僅介紹幾種常用的。在springboot框架中,可以使用注解簡單實現(xiàn)線程的操作,還有AsyncManager的方式,如果需要復(fù)雜的線程操作,可以使用線程池實現(xiàn)。下面根據(jù)具體方法進(jìn)行介紹。

一、注解@Async

springboot框架的注解,使用時也有一些限制,這個在網(wǎng)上也有很多介紹,@Async注解不能在類本身直接調(diào)用,在springboot框架中,可以使用單獨的Service實現(xiàn)異步方法,然后在其他的類中調(diào)用該Service中的異步方法即可,具體如下:

1. 添加注解

在springboot的config中添加 @EnableAsync注解,開啟異步線程功能

package com.thcb.boot.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
/**
 * MyConfig
 *
 * @author thcb
 */
@Configuration
@EnableAsync
public class MyConfig {
    // 自己配置的Config
}

2. 創(chuàng)建異步方法Service和實現(xiàn)類

使用service實現(xiàn)耗時的方法

Service類:

package com.thcb.execute.service;
import org.springframework.scheduling.annotation.Async;
/**
 * IExecuteService
 *
 * @author thcb
 */
public interface IExecuteService {
    /**
     * 一些耗時的操作,使用單獨線程處理
     * 這里就簡單寫了一個sleep5秒的操作
     */
    @Async
    public void sleepingTest();
}

Service實現(xiàn)類:

package com.thcb.execute.service.impl;
import com.thcb.execute.service.IExecuteService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
/**
 * ExecuteService業(yè)務(wù)層處理
 *
 * @author thcb
 */
@Service
public class ExecuteServiceImpl implements IExecuteService {
    private static final Logger log = LoggerFactory.getLogger(ExecuteServiceImpl.class);
    @Override
    public void sleepingTest() {
        log.info("SleepingTest start");
        try {
            Thread.sleep(5000);
        } catch (Exception e) {
            log.error("SleepingTest:" + e.toString());
        }
        log.info("SleepingTest end");
    }
}

3. 調(diào)用異步方法

這里根據(jù)Springboot的框架,在controller層調(diào)用,并使用log查看是否時異步結(jié)果。

controller:

package com.thcb.boot.controller;
import com.thcb.execute.service.IExecuteService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * TestController
 *
 * @author thcb
 */
@RestController
public class TestController {
    private static final Logger log = LoggerFactory.getLogger(TestController.class);
    @Autowired
    private IExecuteService executeService;
    @RequestMapping("/test")
    public String test() {
        return "spring boot";
    }
    @RequestMapping("/executeTask")
    public String executeTask() {
        log.info("executeTask Start!");
        executeService.sleepingTest();
        log.info("executeTask End!");
        return "executeTask";
    }
}

在log查看結(jié)果:

log結(jié)果

接口直接返回了executeTask,并log出executeTask End!在5秒之后,log打出SleepingTest end,說明使用了異步線程處理了executeService.sleepingTest的方法。

二、AsyncManager

使用AsyncManager方法,也是SpringBoot框架中帶的任務(wù)管理器,可以實現(xiàn)異步線程。

1. 創(chuàng)建AsyncManager類

使用AsyncManager首先需要創(chuàng)建一個AsyncManager類,這個在springboot框架中應(yīng)該也是有的:

/**
 * 異步任務(wù)管理器
 *
 * @author thcb
 */
public class AsyncManager {
    /**
     * 操作延遲10毫秒
     */
    private final int OPERATE_DELAY_TIME = 10;
    /**
     * 異步操作任務(wù)調(diào)度線程池
     */
    private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
    /**
     * 單例模式
     */
    private AsyncManager() {
    }
    private static AsyncManager me = new AsyncManager();
    public static AsyncManager me() {
        return me;
    }
    /**
     * 執(zhí)行任務(wù)
     *
     * @param task 任務(wù)
     */
    public void execute(TimerTask task) {
        executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
    }
    /**
     * 停止任務(wù)線程池
     */
    public void shutdown() {
        Threads.shutdownAndAwaitTermination(executor);
    }
}

2. 創(chuàng)建一個耗時的操作類

這里同樣需要創(chuàng)建一個耗時的操作,也是用sleep模擬:

    public TimerTask sleepingTest() {
        return new TimerTask() {
            @Override
            public void run() {
            	// 耗時操作
            	try {
                	Thread.sleep(5000);
        		} catch (Exception e) {
            		log.error("SleepingTest:" + e.toString());
        		}
            }
        };
    }

3. 執(zhí)行異步操作

使用AsyncManager執(zhí)行異步操作也比較簡單,直接調(diào)用即可:

// 異步線程池
    AsyncManager.me().execute(sleepingTest());

三、線程池

使用線程池可以設(shè)定更多的參數(shù),線程池在網(wǎng)上也有很多詳細(xì)的介紹,在這我只介紹一種,帶拒絕策略的線程池。

1. 創(chuàng)建線程池

創(chuàng)建帶有拒絕策略的線程池,并設(shè)定核心線程數(shù),最大線程數(shù),隊列數(shù)和超出核心線程數(shù)量的線程存活時間:

    /**
     * 線程池信息: 核心線程數(shù)量5,最大數(shù)量10,隊列大小20,超出核心線程數(shù)量的線程存活時間:30秒, 指定拒絕策略的
     */
    private static final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 30, TimeUnit.SECONDS,
            new LinkedBlockingQueue<Runnable>(20), new RejectedExecutionHandler() {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            log.error("有任務(wù)被拒絕執(zhí)行了");
        }
    });

2. 創(chuàng)建一個耗時的操作類

由于線程池需要傳入一個Runnable,所以此類繼承Runnable,還是用sleep模擬耗時操作。

    /**
     * 耗時操作
     */
    static class MyTask implements Runnable {
        private int taskNum;
        public MyTask(int num) {
            this.taskNum = num;
        }
        @Override
        public void run() {
            System.out.println("正在執(zhí)行task " + taskNum);
            try {
                Thread.sleep(4000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("task " + taskNum + "執(zhí)行完畢");
        }
    }

3. 執(zhí)行線程池

開啟線程池,這里通過一個for循環(huán)模擬一下,可以看一下log輸出,有興趣的可以修改一下for循環(huán)和sleep的數(shù)值,看看線程池具體的操作和拒絕流程。

        for (int i = 0; i < 20; i++) {
            MyTask myTask = new MyTask(i);
            threadPoolExecutor.execute(myTask);
            System.out.println("線程池中線程數(shù)目:" + threadPoolExecutor.getPoolSize() + ",隊列中等待執(zhí)行的任務(wù)數(shù)目:" +
                    threadPoolExecutor.getQueue().size() + ",已執(zhí)行完別的任務(wù)數(shù)目:" + threadPoolExecutor.getCompletedTaskCount());
        }
        threadPoolExecutor.shutdown();

總結(jié)

在此寫一些線程操作需要注意的地方:

  • 線程數(shù)量和cpu有關(guān),使用線程時一定要注意線程的釋放,否則會導(dǎo)致cpu線程數(shù)量耗盡;
  • 使用注解完成的線程操作,不可以在自己的類中實現(xiàn)調(diào)用,因為注解最后也是通過代理的方式完成異步線程的,最好時在單獨的一個service中寫;
  • 線程池最好單獨寫,使用static和final修飾,保證所有使用該線程池的地方使用的是一個線程池,而不能每次都new一個線程池出來,每次都new一個就沒有意義了。

以上就是三種線程池的操作,寫的不算很詳細(xì),有興趣的同學(xué)可以自己在深入研究一下,還有Java8新加的CompletableFuture,可以單獨寫一篇文章了,在此篇就不再介紹了:)

到此這篇關(guān)于java開啟異步線程的幾種方法(@Async,AsyncManager,線程池)的文章就介紹到這了,更多相關(guān)java開啟異步線程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot異步調(diào)用方法實現(xiàn)場景代碼實例

    SpringBoot異步調(diào)用方法實現(xiàn)場景代碼實例

    這篇文章主要介紹了SpringBoot異步調(diào)用方法實現(xiàn)場景代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • mybatis?@InsertProvider報錯問題及解決

    mybatis?@InsertProvider報錯問題及解決

    這篇文章主要介紹了mybatis?@InsertProvider報錯的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • java組件SmartUpload和FileUpload實現(xiàn)文件上傳功能

    java組件SmartUpload和FileUpload實現(xiàn)文件上傳功能

    這篇文章主要為大家詳細(xì)介紹了java組件SmartUpload和FileUpload實現(xiàn)文件上傳功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • Java Jackson核心注解使用詳解

    Java Jackson核心注解使用詳解

    這篇文章主要介紹了Java Jackson核心注解的使用,??Jackson核心注解??用于控制Java對象與JSON之間的序列化、反序列化行為,簡化字段映射、格式轉(zhuǎn)換與數(shù)據(jù)過濾,需要的朋友可以參考下
    2025-05-05
  • JAVA 內(nèi)存溢出案例匯總

    JAVA 內(nèi)存溢出案例匯總

    這篇文章主要介紹了JAVA 內(nèi)存溢出案例的匯總,文中講解非常細(xì)致,幫助各位工作學(xué)習(xí)時避免內(nèi)存溢出,感興趣的朋友可以了解下
    2020-07-07
  • Java實現(xiàn)本地緩存的四種方法實現(xiàn)與對比

    Java實現(xiàn)本地緩存的四種方法實現(xiàn)與對比

    本地緩存的優(yōu)點就是速度非???沒有網(wǎng)絡(luò)消耗,本地緩存比如 caffine,guava cache 這些都是比較常用的,下面我們來看看這四種緩存的具體實現(xiàn)吧
    2025-08-08
  • 淺談SpringMVC對RESTfull的支持

    淺談SpringMVC對RESTfull的支持

    這篇文章主要介紹了淺談SpringMVC對RESTfull的支持,分享了相關(guān)配置代碼,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-02-02
  • SpringBoot JPA實現(xiàn)增刪改查、分頁、排序、事務(wù)操作等功能示例

    SpringBoot JPA實現(xiàn)增刪改查、分頁、排序、事務(wù)操作等功能示例

    本篇文章主要介紹了SpringBoot JPA實現(xiàn)增刪改查、分頁、排序、事務(wù)操作等功能示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-03-03
  • javax.persistence中@Column定義字段類型方式

    javax.persistence中@Column定義字段類型方式

    這篇文章主要介紹了javax.persistence中@Column定義字段類型方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • SpringCloud?Gateway實現(xiàn)請求解密和響應(yīng)加密的過程解析

    SpringCloud?Gateway實現(xiàn)請求解密和響應(yīng)加密的過程解析

    這篇文章主要介紹了SpringCloud?Gateway實現(xiàn)請求解密和響應(yīng)加密的相關(guān)知識,本文環(huán)境使用比較新的?Java?17?和?SpringBoot?3.1.5,對應(yīng)到Spring的版本是?6.0.13,本文重心是網(wǎng)關(guān)項目,需要的朋友可以參考下
    2023-11-11

最新評論

门头沟区| 荔浦县| 蕉岭县| 通江县| 江门市| 旬阳县| 黄石市| 江永县| 北碚区| 疏附县| 鹿邑县| 漠河县| 蕉岭县| 镶黄旗| 永仁县| 河津市| 灵宝市| 兰州市| 汉沽区| 稷山县| 屯留县| 本溪市| 微山县| 屏山县| 成安县| 多伦县| 巴林左旗| 连云港市| 济源市| 含山县| 关岭| 治多县| 伽师县| 谷城县| 江津市| 上栗县| 永清县| 邵武市| 额济纳旗| 天津市| 巴林左旗|