精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

異步編程的幾種種實現方式(下)

jf_78858299 ? 來源:微觀技術 ? 作者:Tom哥 ? 2023-02-15 16:15 ? 次閱讀

五、 SpringBoot 注解 @Async

除了硬編碼的異步編程處理方式,SpringBoot 框架還提供了 注解式 解決方案,以 方法體 為邊界,方法體內部的代碼邏輯全部按異步方式執行。

首先,使用 @EnableAsync 啟用異步注解

@SpringBootApplication
@EnableAsync
public class StartApplication {

    public static void main(String[] args) {
        SpringApplication.run(StartApplication.class, args);
    }
}

自定義線程池:

@Configuration
@Slf4j
public class ThreadPoolConfiguration {

    @Bean(name = "defaultThreadPoolExecutor", destroyMethod = "shutdown")
    public ThreadPoolExecutor systemCheckPoolExecutorService() {

        return new ThreadPoolExecutor(3, 10, 60, TimeUnit.SECONDS,
                new LinkedBlockingQueue(10000),
                new ThreadFactoryBuilder().setNameFormat("default-executor-%d").build(),
                (r, executor) -> log.error("system pool is full! "));
    }
}

在異步處理的方法上添加注解 @Async ,當對 execute 方法 調用時,通過自定義的線程池 defaultThreadPoolExecutor 異步化執行 execute 方法

@Service
public class AsyncServiceImpl implements AsyncService {

    @Async("defaultThreadPoolExecutor")
    public Boolean execute(Integer num) {
        System.out.println("線程:" + Thread.currentThread().getName() + " , 任務:" + num);
        return true;
    }

}

用 @Async 注解標記的方法,稱為異步方法。在spring boot應用中使用 @Async 很簡單:

  • 調用異步方法類上或者啟動類加上注解 @EnableAsync
  • 在需要被異步調用的方法外加上 @Async
  • 所使用的 @Async 注解方法的類對象應該是Spring容器管理的bean對象;

六、Spring ApplicationEvent 事件

事件機制在一些大型項目中被經常使用,Spring 專門提供了一套事件機制的接口,滿足了架構原則上的解耦。

ApplicationContext 通過 ApplicationEvent 類和 ApplicationListener 接口進行事件處理。如果將實現 ApplicationListener 接口的 bean 注入到上下文中,則每次使用 ApplicationContext 發布 ApplicationEvent 時,都會通知該 bean。本質上,這是標準的觀察者設計模式。

ApplicationEvent 是由 Spring 提供的所有 Event 類的基類

首先,自定義業務事件子類,繼承自 ApplicationEvent,通過泛型注入業務模型參數類。相當于 MQ 的消息體。

public class OrderEvent extends AbstractGenericEvent {
    public OrderEvent(OrderModel source) {
        super(source);
    }
}

然后,編寫事件監聽器。ApplicationListener 接口是由 Spring 提供的事件訂閱者必須實現的接口,我們需要定義一個子類,繼承 ApplicationListener。相當于 MQ 的消費端

@Component
public class OrderEventListener implements ApplicationListener<OrderEvent> {
    @Override
    public void onApplicationEvent(OrderEvent event) {

        System.out.println("【OrderEventListener】監聽器處理!" + JSON.toJSONString(event.getSource()));

    }
}

最后,發布事件,把某個事件告訴所有與這個事件相關的監聽器。相當于 MQ 的生產端。

OrderModel orderModel = new OrderModel();
orderModel.setOrderId((long) i);
orderModel.setBuyerName("Tom-" + i);
orderModel.setSellerName("judy-" + i);
orderModel.setAmount(100L);
// 發布Spring事件通知
SpringUtils.getApplicationContext().publishEvent(new OrderEvent(orderModel));

加個餐:

[消費端]線程:http-nio-8090-exec-1,消費事件 {"amount":100.0,"buyerName":"Tom-1","orderId":1,"sellerName":"judy-1"}
[生產端]線程:http-nio-8090-exec-1,發布事件 1
[消費端]線程:http-nio-8090-exec-1,消費事件 {"amount":100.0,"buyerName":"Tom-2","orderId":2,"sellerName":"judy-2"}
[生產端]線程:http-nio-8090-exec-1,發布事件 2
[消費端]線程:http-nio-8090-exec-1,消費事件 {"amount":100.0,"buyerName":"Tom-3","orderId":3,"sellerName":"judy-3"}
[生產端]線程:http-nio-8090-exec-1,發布事件 3

上面是跑了個demo的運行結果,我們發現無論生產端還是消費端,使用了同一個線程 http-nio-8090-exec-1,Spring 框架的事件機制默認是同步阻塞的。只是在代碼規范方面做了解耦,有較好的擴展性,但底層還是采用同步調用方式。

那么問題來了,如果想實現異步調用,如何處理?

我們需要手動創建一個 SimpleApplicationEventMulticaster,并設置 TaskExecutor,此時所有的消費事件采用異步線程執行。

@Component
public class SpringConfiguration {

    @Bean
    public SimpleApplicationEventMulticaster applicationEventMulticaster(@Qualifier("defaultThreadPoolExecutor") ThreadPoolExecutor defaultThreadPoolExecutor) {
        SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = new SimpleApplicationEventMulticaster();
        simpleApplicationEventMulticaster.setTaskExecutor(defaultThreadPoolExecutor);
        return simpleApplicationEventMulticaster;
    }

}

我們看下改造后的運行結果:

[生產端]線程:http-nio-8090-exec-1,發布事件 1
[生產端]線程:http-nio-8090-exec-1,發布事件 2
[生產端]線程:http-nio-8090-exec-1,發布事件 3
[消費端]線程:default-executor-1,消費事件 {"amount":100.0,"buyerName":"Tom-2","orderId":2,"sellerName":"judy-2"}
[消費端]線程:default-executor-2,消費事件 {"amount":100.0,"buyerName":"Tom-1","orderId":1,"sellerName":"judy-1"}
[消費端]線程:default-executor-0,消費事件 {"amount":100.0,"buyerName":"Tom-3","orderId":3,"sellerName":"judy-3"}

SimpleApplicationEventMulticaster 這個我們自己實例化的 Bean 與系統默認的加載順序如何?會不會有沖突?

查了下 Spring 源碼,處理邏輯在 AbstractApplicationContext#initApplicationEventMulticaster 方法中,通過 beanFactory 查找是否有自定義的 Bean,如果沒有,容器會自己 new 一個 SimpleApplicationEventMulticaster 對象注入到容器中。

圖片

代碼地址:https://github.com/aalansehaiyang/wx-project

七、消息隊列

異步架構是互聯網系統中一種典型架構模式,與同步架構相對應。而消息隊列天生就是這種異步架構,具有超高吞吐量和超低時延。

消息隊列異步架構的主要角色包括消息生產者、消息隊列和消息消費者。

圖片

消息生產者就是主應用程序,生產者將調用請求封裝成消息發送給消息隊列。

消息隊列的職責就是緩沖消息,等待消費者消費。根據消費方式又分為點對點模式發布訂閱模式兩種。

消息消費者,用來從消息隊列中拉取、消費消息,完成業務邏輯處理。

當然市面上消息隊列框架非常多,常見的有RabbitMQ、Kafka、RocketMQ、ActiveMQ 和 Pulsar 等

圖片

不同的消息隊列的功能特性會略有不同,但整體架構類似,這里就不展開了。

我們只需要記住一個關鍵點,借助消息隊列這個中間件可以高效的實現異步編程。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 編程
    +關注

    關注

    88

    文章

    3595

    瀏覽量

    93600
  • 代碼
    +關注

    關注

    30

    文章

    4751

    瀏覽量

    68357
  • spring
    +關注

    關注

    0

    文章

    338

    瀏覽量

    14311
收藏 人收藏

    評論

    相關推薦

    Spring Boot如何實現異步任務

    Spring Boot 提供了多種方式實現異步任務,這里介紹三種主要實現方式。 1、基于注解 @Async @Async 注解是 Spri
    的頭像 發表于 09-30 10:32 ?1407次閱讀

    USART異步工作方式編程

    USART異步工作方式編程 串行通信的接收有查詢和中斷2種方式,在實際應用中,一般不采用查詢接收數據,常用的是中斷接收數據。發送有中斷發送和非中斷發送,在下面的例程中我們采用了中斷接收
    發表于 09-08 09:48

    【我是電子發燒友】低功耗設計的最佳編程模型:異步編程

    異步編程可以編寫出速度快、資源省的高效程序,可以在單線程環境實現高并發,可以在沒有操作系統的情況實現
    發表于 04-29 20:30

    有哪幾種方式可以通過Keil模塊化編程實現流水燈設計?

    Keil的模塊化編程是什么?有哪幾種方式可以通過Keil模塊化編程實現流水燈設計?如何對流水燈設計進行Proteus仿真?
    發表于 07-14 07:17

    幾種最基本的通訊方式解釋與總結

    問題的地方,麻煩各位及時反饋一,謝謝。在對幾種協議進行介紹之前,先介紹三個基本概念:(1)異步和同步假設現在有兩臺設備A、B之間需要盡心通信,如果A與B兩臺設備使用的是同一個時鐘信號,則稱為同步,如果使用的不是同一個時鐘信號,
    發表于 02-23 07:30

    相機曝光模式有哪幾種種類?如何設置曝光模式?

    相機曝光模式有哪幾種種類?如何設置曝光模式?
    發表于 03-02 09:34

    Modbus通訊協議的幾種實現方式

    Modbus通訊的方式   針對Modbus的串口和TCP兩種不同的方式,在LabVIEW中通常可以通過以下幾種方法實現Modbus通訊。其中一些
    發表于 05-05 16:19

    請問一plc可以實現無線通信嗎?有幾種方式

    請問一plc可以實現無線通信嗎?有幾種方式?
    發表于 05-09 17:23

    異步傳輸方式的HDLC協議的實現

    研究實現了一種 HDLC (High Level Data Link Contr01)協議的改進方法,該方法把HDLC協議傳統的同步傳榆方式改成了異步傳輸方式,既保留了原有HDLC協議
    發表于 07-20 17:25 ?62次下載
    <b class='flag-5'>異步</b>傳輸<b class='flag-5'>方式</b>的HDLC協議的<b class='flag-5'>實現</b>

    快速改變濾波器中心頻率的幾種實現方式

    快速改變濾波器中心頻率的幾種實現方式,下來看看
    發表于 01-07 21:24 ?12次下載

    在Python中實現異步編程(附源碼)

    異步編程是并行編程的一種方式。單個工作單元獨立于主應用程序線程運行,并通知調用線程其完成、失敗情況或進度。下面這張圖理解起來會更直觀一些:
    的頭像 發表于 10-27 14:36 ?2331次閱讀
    在Python中<b class='flag-5'>實現</b><b class='flag-5'>異步</b><b class='flag-5'>編程</b>(附源碼)

    異步編程幾種種實現方式(上)

    異步編程是讓程序并發運行的一種手段。它允許多個事件同時發生,當程序調用需要長時間運行的方法時,它不會阻塞當前的執行流程,程序可以繼續運行。
    的頭像 發表于 02-15 16:15 ?720次閱讀
    <b class='flag-5'>異步</b><b class='flag-5'>編程</b>的<b class='flag-5'>幾種種</b><b class='flag-5'>實現</b><b class='flag-5'>方式</b>(上)

    三相異步電動機的幾種調速方式

    介紹了幾種調速的方式
    發表于 10-07 11:18 ?0次下載

    java實現多線程的幾種方式

    Java實現多線程的幾種方式 多線程是指程序中包含了兩個或以上的線程,每個線程都可以并行執行不同的任務或操作。Java中的多線程可以提高程序的效率和性能,使得程序可以同時處理多個任務。 Java提供
    的頭像 發表于 03-14 16:55 ?579次閱讀

    籠形異步電機常用的降壓啟動方式

    ,保護電機和電網。 籠形異步電機降壓啟動方式概述 籠形異步電機在啟動時,由于轉子的慣性和負載的影響,需要較大的啟動轉矩。為了減少啟動電流,通常采用以下幾種降壓啟動
    的頭像 發表于 09-03 15:18 ?1258次閱讀