吴忠躺衫网络科技有限公司

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

SpringBoot實(shí)現(xiàn)多線程

jf_96884364 ? 來源:jf_96884364 ? 作者:jf_96884364 ? 2023-01-12 16:59 ? 次閱讀

代碼地址:https://github.com/Snowstorm0/learn-async

1 線程同步和異步

線程同步 :A線程要請(qǐng)求某個(gè)資源,但是此資源正在被B線程使用中,因?yàn)橥綑C(jī)制存在,A只能等待下去。耗時(shí)較長,安全性較高。

線程異步 :A線程要請(qǐng)求某個(gè)資源,但是此資源正在被B線程使用中,因?yàn)闆]有同步機(jī)制存在,A線程仍然請(qǐng)求的到。

一個(gè)進(jìn)程啟動(dòng)的多個(gè)不相干的進(jìn)程,他們之間的相互關(guān)系為異步;同步必須執(zhí)行到底后才能執(zhí)行其他操作,異步可同時(shí)執(zhí)行。

多個(gè)線程執(zhí)行的時(shí)候需要同步,如果是單線程則不需要同步。

2 異步實(shí)例

主方法和被調(diào)用的方法必須是不同的類,才能實(shí)現(xiàn)多線程。

2.1 啟動(dòng)類

使用@EnableAsync來開啟 SpringBoot 對(duì)于異步任務(wù)的支持。

Application:

@SpringBootApplication
@EnableAsync
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

2.2 線程池

配置類實(shí)現(xiàn)接口AsyncConfigurator,返回一個(gè)ThreadPoolTaskExecutor線程池對(duì)象。

config/AsyncConfig:

@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {

    // ThredPoolTaskExcutor的處理流程
    // 當(dāng)池子大小小于corePoolSize,就新建線程,并處理請(qǐng)求
    // 當(dāng)池子大小等于corePoolSize,把請(qǐng)求放入workQueue中,池子里的空閑線程就去workQueue中取任務(wù)并處理
    // 當(dāng)workQueue放不下任務(wù)時(shí),就新建線程入池,并處理請(qǐng)求,如果池子大小撐到了maximumPoolSize,就用RejectedExecutionHandler來做拒絕處理
    // 當(dāng)池子的線程數(shù)大于corePoolSize時(shí),多余的線程會(huì)等待keepAliveTime長時(shí)間,如果無請(qǐng)求可處理就自行銷毀

    @Override
    @Bean
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心線程數(shù):線程池創(chuàng)建的時(shí)候初始化的線程數(shù)
        executor.setCorePoolSize(10);
        // 最大線程數(shù):線程池最大的線程數(shù),只有緩沖隊(duì)列滿了之后才會(huì)申請(qǐng)超過核心線程數(shù)的線程
        executor.setMaxPoolSize(100);
        // 緩沖隊(duì)列:用來緩沖執(zhí)行任務(wù)的隊(duì)列
        executor.setQueueCapacity(50);
        // 線程池關(guān)閉:等待所有任務(wù)都完成再關(guān)閉
        executor.setWaitForTasksToCompleteOnShutdown(true);
        // 等待時(shí)間:等待5秒后強(qiáng)制停止
        executor.setAwaitTerminationSeconds(5);
        // 允許空閑時(shí)間:超過核心線程之外的線程到達(dá)60秒后會(huì)被銷毀
        executor.setKeepAliveSeconds(60);
        // 線程名稱前綴
        executor.setThreadNamePrefix("learn-Async-");
        // 初始化線程
        executor.initialize();
        return executor;
    }

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

2.3 controller

通過該層調(diào)用測試 Async。

@RestController
@RequestMapping("/homepage")
public class AsyncController {
    @Autowired
    AsyncService asyncTaskService;
    @GetMapping("/learnAsync")
    public String learnAsync(){
        for (int i = 0; i < 10; i++) {
            asyncTaskService.executeAsyncTask(i);
        }
        return "1";
    }
}

2.4 service

通過@Async注解表明該方法是異步方法,如果注解在類上,那表明這個(gè)類里面的所有方法都是異步的。

@Service
public class AsyncService {
    private final static Logger logger = LoggerFactory.getLogger(com.spring.boot.service.AsyncService.class);
    @Async  // 表明該方法是異步方法。如果注解在類上,那表明類里面的所有方法都是異步
    public void executeAsyncTask(int i) {
        logger.info("\\t 完成任務(wù)" + i);
        System.out.println("線程" + Thread.currentThread().getName() + " 執(zhí)行異步任務(wù):" + i);
    }
}

2.5 輸出

3 Future 類

修改service層,分別使用同步調(diào)用、異步調(diào)用無返回、異步調(diào)用使用 Future 返回。

3.1 同步調(diào)用

public long subBySync() throws Exception {
    long start = System.currentTimeMillis();
    long sum = 0;
    long end = System.currentTimeMillis();
    sum = end - start;
    return sum;
}

3.2 異步調(diào)用無返回

@Async
public void subByVoid() throws Exception {
    long start = System.currentTimeMillis();
    long sum = 0;
    long end = System.currentTimeMillis();
    sum = end - start;
}

3.3 異步調(diào)用 Future 返回

controller:

Future task = asyncTaskService.subByAsync();

service:

@Async
public Future subByAsync() throws Exception {
    long start = System.currentTimeMillis();
    long sum = 0;
    long end = System.currentTimeMillis();
    sum = end - start;
    return new AsyncResult<>(sum);
}

4 CompletableFuture 類

若使用 Future 出現(xiàn)報(bào)錯(cuò):

無法判斷org.springframework.scheduling.annotation.AsyncResult<>的類型參數(shù)

不存在類型變量V的實(shí)例,使org.springframework.scheduling.annotation.AsyncResult符合XXX

可以使用 CompletableFuture 類:

@Asyncpublic 
CompletableFuture> subByAsyncMap() throws Exception {
    Map res = new HashMap<>();
    return CompletableFuture.completedFuture(res);
}

5 線程關(guān)閉

當(dāng)線程數(shù)量超過核心線程數(shù)量之后,運(yùn)行完畢的舊的線程會(huì)被關(guān)閉。

可以通過定時(shí)任務(wù)測試。

batch/ScheduledTaskService:

@Component
@EnableScheduling
public class ScheduledTaskService {
    @Autowired
    AsyncService asyncService;
    @Scheduled(cron = "1/1 * * * * ? ")  //1s一次
    public void learnCron(){
        asyncService.learnScheduledAsync();
    }
}

在 AsyncService 添加方法:

// 使用定時(shí)任務(wù)調(diào)用此方法創(chuàng)建線程
@Async
public void learnScheduledAsync(){
    Long timeLong = System.currentTimeMillis();
    SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //設(shè)置格式
    String timeString = timeFormat.format(timeLong);
    System.out.println("線程" + Thread.currentThread().getName());
    System.out.println("timeString:" + timeString + "\\n");
}

在異步配置(AsyncConfig)中已設(shè)置核心線程數(shù)為10:

// 核心線程數(shù):線程池創(chuàng)建的時(shí)候初始化的線程數(shù)
executor.setCorePoolSize(10);

運(yùn)行可以觀察輸出,線程數(shù)達(dá)到10后會(huì)再一次從1開始。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • JAVA
    +關(guān)注

    關(guān)注

    19

    文章

    2974

    瀏覽量

    105140
  • 多線程
    +關(guān)注

    關(guān)注

    0

    文章

    278

    瀏覽量

    20072
  • spring
    +關(guān)注

    關(guān)注

    0

    文章

    340

    瀏覽量

    14388
  • Boot
    +關(guān)注

    關(guān)注

    0

    文章

    150

    瀏覽量

    35944
  • SpringBoot
    +關(guān)注

    關(guān)注

    0

    文章

    174

    瀏覽量

    201
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Java多線程的用法

    能力。 什么是進(jìn)程 是指正在運(yùn)行的程序的實(shí)例。 每個(gè)進(jìn)程都擁有自己的內(nèi)存空間、代碼、數(shù)據(jù)和文件等資源,可以獨(dú)立運(yùn)行、調(diào)度和管理。在操作系統(tǒng)中,進(jìn)程是系統(tǒng)資源分配的最小單位,是實(shí)現(xiàn)多任務(wù)的基礎(chǔ)。 Java多線程 Java多線程是指
    的頭像 發(fā)表于 09-30 17:07 ?1005次閱讀

    利用線程的互斥實(shí)現(xiàn)串口多線程收發(fā)數(shù)據(jù)

    利用線程的互斥實(shí)現(xiàn)串口多線程收發(fā)數(shù)據(jù)從而達(dá)到流水燈的效果。多線程串口編程主要分為三步,第一部分,連接串口及開發(fā)板,確定設(shè)備號(hào);第二部分為串口參數(shù)的設(shè)置;第三部分為
    發(fā)表于 01-07 08:08

    多線程技術(shù)在串口通信中的應(yīng)用

            首先介紹了多線程技術(shù)的基本原理,然后討論了多線程技術(shù)在串口通信中的應(yīng)用,并給出了實(shí)現(xiàn)的方法和步驟。關(guān)鍵詞:
    發(fā)表于 09-04 09:10 ?18次下載

    多線程實(shí)現(xiàn)網(wǎng)絡(luò)入侵檢測的負(fù)載均衡

    本內(nèi)容詳細(xì)介紹了多線程實(shí)現(xiàn) 網(wǎng)絡(luò)入侵 檢測的負(fù)載均衡
    發(fā)表于 06-29 16:01 ?20次下載
    <b class='flag-5'>多線程</b><b class='flag-5'>實(shí)現(xiàn)</b>網(wǎng)絡(luò)入侵檢測的負(fù)載均衡

    實(shí)現(xiàn)多線程IP和DomainName相互轉(zhuǎn)換_Delphi教程

    Delphi教程實(shí)現(xiàn)多線程IP和DomainName相互轉(zhuǎn)換,很好的Delphi學(xué)習(xí)資料。
    發(fā)表于 03-16 14:58 ?7次下載

    Delphi教程_實(shí)現(xiàn)多線程共享探測

    Delphi教程實(shí)現(xiàn)多線程共享探測,很好的Delphi學(xué)習(xí)資料。
    發(fā)表于 03-16 14:59 ?3次下載

    多線程與聊天室程序的創(chuàng)建

    多線程程序的編寫,多線程應(yīng)用中容易出現(xiàn)的問題。互斥對(duì)象的講解,如何采用互斥對(duì)象來實(shí)現(xiàn)多線程的同步。如何利用命名互斥對(duì)象保證應(yīng)用程序只有一個(gè)實(shí)例運(yùn)行。應(yīng)用
    發(fā)表于 05-16 15:22 ?0次下載

    多線程好還是單線程好?單線程多線程的區(qū)別 優(yōu)缺點(diǎn)分析

    摘要:如今單線程多線程已經(jīng)得到普遍運(yùn)用,那么到底多線程好還是單線程好呢?單線程多線程的區(qū)別又
    發(fā)表于 12-08 09:33 ?8.2w次閱讀

    mfc多線程編程實(shí)例及代碼,mfc多線程間通信介紹

    摘要:本文主要以MFC多線程為中心,分別對(duì)MFC多線程的實(shí)例、MFC多線程之間的通信展開的一系列研究,下面我們來看看原文。
    發(fā)表于 12-08 15:23 ?1.8w次閱讀
    mfc<b class='flag-5'>多線程</b>編程實(shí)例及代碼,mfc<b class='flag-5'>多線程</b>間通信介紹

    什么是多線程編程?多線程編程基礎(chǔ)知識(shí)

    摘要:多線程編程是現(xiàn)代軟件技術(shù)中很重要的一個(gè)環(huán)節(jié)。要弄懂多線程,這就要牽涉到多進(jìn)程。本文主要以多線程編程以及多線程編程相關(guān)知識(shí)而做出的一些結(jié)論。
    發(fā)表于 12-08 16:30 ?1.3w次閱讀

    labview AMC多線程

    labview_AMC多線程
    發(fā)表于 08-21 10:31 ?32次下載

    多線程如何保證數(shù)據(jù)的同步

    多線程編程是一種并發(fā)編程的方法,意味著程序中同時(shí)運(yùn)行多個(gè)線程,每個(gè)線程可獨(dú)立執(zhí)行不同的任務(wù),共享同一份數(shù)據(jù)。由于多線程并發(fā)執(zhí)行的特點(diǎn),會(huì)引發(fā)數(shù)據(jù)同步的問題,即保證多個(gè)
    的頭像 發(fā)表于 11-17 14:22 ?1315次閱讀

    mfc多線程編程實(shí)例

    (圖形用戶界面)應(yīng)用程序的開發(fā)。在這篇文章中,我們將重點(diǎn)介紹MFC中的多線程編程。 多線程編程在軟件開發(fā)中非常重要,它可以實(shí)現(xiàn)程序的并發(fā)執(zhí)行,提高程序的效率和響應(yīng)速度。MFC提供了豐富的多線程
    的頭像 發(fā)表于 12-01 14:29 ?1569次閱讀

    java實(shí)現(xiàn)多線程的幾種方式

    Java實(shí)現(xiàn)多線程的幾種方式 多線程是指程序中包含了兩個(gè)或以上的線程,每個(gè)線程都可以并行執(zhí)行不同的任務(wù)或操作。Java中的
    的頭像 發(fā)表于 03-14 16:55 ?782次閱讀

    socket 多線程編程實(shí)現(xiàn)方法

    在現(xiàn)代網(wǎng)絡(luò)編程中,多線程技術(shù)被廣泛應(yīng)用于提高服務(wù)器的并發(fā)處理能力。Socket編程是網(wǎng)絡(luò)通信的基礎(chǔ),而將多線程技術(shù)應(yīng)用于Socket編程,可以顯著提升服務(wù)器的性能。 多線程編程的基本概念 多線
    的頭像 發(fā)表于 11-12 14:16 ?465次閱讀
    赌百家乐官网的心得体会| 下载百家乐棋牌大厅| 澳门美高梅金殿| 实战百家乐博彩正网| 淘金百家乐官网现金网| 肯博百家乐的玩法技巧和规则| 澳门百家乐官网玩大小| 威尼斯人娱乐的微博| 百家乐官网娱乐平台会员注册| 肯博百家乐的玩法技巧和规则| 百家乐官网策略网络游戏信誉怎么样 | 百家乐3宜3忌| 百家乐官网有方式赢钱吗| 百家乐博娱乐网赌百家乐的玩法技巧和规则 | 百家乐vshow| 百家乐官网赌机破解| 大发8888| 百家乐断缆赢钱| 百家乐官网波音平台开户导航| 大发888常见断续| 澳门百家乐打法精华| 专业的百家乐官网玩家| 南和县| 大发888扑克合营商| 百家乐2号死机| 涂山百家乐官网的玩法技巧和规则 | 博九网| 百家乐单注打| 怎么玩百家乐网上赌博| 波音百家乐官网现金网| 至尊国际娱乐| 免水百家乐的玩法技巧和规则 | 南宁百家乐的玩法技巧和规则| 凯旋门百家乐游戏| 御匾会百家乐官网的玩法技巧和规则 | 杨公24山向水法吉凶断| 百家乐官网有没有破解之法| 网上百家乐官网哪家最好| 六合彩投注网| 德州扑克荷官招聘| 百家乐波音独家注册送彩|