Spring @Async實現非同步呼叫示例
什麼是“非同步呼叫”?
“非同步呼叫”對應的是“同步呼叫”,同步呼叫指程式按照定義順序依次執行,每一行程式都必須等待上一行程式執行完成之後才能執行;非同步呼叫指程式在順序執行時,不等待非同步呼叫的語句返回結果就執行後面的程式。
同步呼叫
下面通過一個簡單示例來直觀的理解什麼是同步呼叫:
定義Task類,建立三個處理函式分別模擬三個執行任務的操作,操作消耗時間隨機取(10秒內)
package com.dxz.demo1; import java.util.Random; import org.springframework.stereotype.Component;import org.springframework.web.bind.annotation.RequestMapping; /** * 定義3個任務 */ @Component public class Task1 { // 定義一個隨機物件. public static Random random = new Random(); // 任務一; public void doTaskOne() throws Exception { System.out.println("開始做任務一"); longstart = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); System.out.println("完成任務一,耗時:" + (end - start) + "毫秒"); } // 任務二; public void doTaskTwo() throws Exception { System.out.println("開始做任務二");long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); System.out.println("完成任務二,耗時:" + (end - start) + "毫秒"); } // 任務3; public void doTaskThree() throws Exception { System.out.println("開始做任務三"); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); System.out.println("完成任務三,耗時:" + (end - start) + "毫秒"); } }
編寫一個訪問方法:
package com.dxz.demo1; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.dxz.HelloApplication; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = HelloApplication.class) public class Task1Test { @Autowired private Task1 task1; //測試task1. @Test public void task1() throws Exception{ task1.doTaskOne(); task1.doTaskTwo(); task1.doTaskThree(); } }
執行可以看到類似如下輸出:
開始做任務一 2017-04-28 18:02:57.397 WARN 11016 --- [cTaskExecutor-1] o.s.a.r.l.SimpleMessageListenerContainer : Consumer raised exception, processing can restart if the connection factory supports it. Exception summary: org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused: connect 2017-04-28 18:02:57.398 INFO 11016 --- [cTaskExecutor-1] o.s.a.r.l.SimpleMessageListenerContainer : Restarting Consumer: tags=[{}], channel=null, acknowledgeMode=AUTO local queue size=0 完成任務一,耗時:7740毫秒 開始做任務二 完成任務二,耗時:723毫秒 開始做任務三 2017-04-28 18:03:03.415 WARN 11016 --- [cTaskExecutor-2] o.s.a.r.l.SimpleMessageListenerContainer : Consumer raised exception, processing can restart if the connection factory supports it. Exception summary: org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused: connect 2017-04-28 18:03:03.415 INFO 11016 --- [cTaskExecutor-2] o.s.a.r.l.SimpleMessageListenerContainer : Restarting Consumer: tags=[{}], channel=null, acknowledgeMode=AUTO local queue size=0 完成任務三,耗時:5047毫秒
非同步呼叫
上述的同步呼叫雖然順利的執行完了三個任務,但是可以看到執行時間比較長,若這三個任務本身之間不存在依賴關係,可以併發執行的話,同步呼叫在執行效率方面就比較差,可以考慮通過非同步呼叫的方式來併發執行。
在Spring Boot中,我們只需要通過使用@Async
註解就能簡單的將原來的同步函式變為非同步函式,Task類改在為如下模式:
package com.dxz.demo1; import java.util.Random; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.RequestMapping; /** * 定義3個任務 */ @Component public class Task2 { // 定義一個隨機物件. public static Random random = new Random(); // 任務一; @Async public void doTaskOne() throws Exception { System.out.println("開始做任務一"); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); System.out.println("完成任務一,耗時:" + (end - start) + "毫秒"); } // 任務二; @Async public void doTaskTwo() throws Exception { System.out.println("開始做任務二"); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); System.out.println("完成任務二,耗時:" + (end - start) + "毫秒"); } // 任務3; @Async public void doTaskThree() throws Exception { System.out.println("開始做任務三"); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); System.out.println("完成任務三,耗時:" + (end - start) + "毫秒"); } }
為了讓@Async註解能夠生效,還需要在Spring Boot的主程式中配置@EnableAsync,如下所示:
package com.dxz; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableAsync; @EnableAsync @SpringBootApplication public class HelloApplication { public static void main(String[] args) { SpringApplication.run(HelloApplication.class, args); } }
編寫測試方法:
package com.dxz.demo1; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.web.bind.annotation.RequestMapping; import com.dxz.HelloApplication; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = HelloApplication.class) public class Task2Test { @Autowired private Task2 task2; //測試task1. @Test public void task1() throws Exception{ task2.doTaskOne(); task2.doTaskTwo(); task2.doTaskThree(); } }
此時可以反覆執行單元測試,您可能會遇到各種不同的結果,比如:
開始做任務一
開始做任務二
開始做任務三
修改下測試類:
package com.dxz.demo1; import java.util.concurrent.TimeUnit; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.web.bind.annotation.RequestMapping; import com.dxz.HelloApplication; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = HelloApplication.class) public class Task2Test { @Autowired private Task2 task2; // 測試task1. @Test public void task1() throws Exception { task2.doTaskOne(); task2.doTaskTwo(); task2.doTaskThree(); System.out.println("i'm here"); TimeUnit.SECONDS.sleep(15); System.out.println("over"); } }
jieguo:
i'm here
開始做任務二
開始做任務一
開始做任務三
完成任務三,耗時:1280毫秒
2017-04-28 18:25:36.936 WARN 17848 --- [cTaskExecutor-1] o.s.a.r.l.SimpleMessageListenerContainer : Consumer raised exception, processing can restart if the connection factory supports it. Exception summary: org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused: connect
2017-04-28 18:25:36.938 INFO 17848 --- [cTaskExecutor-1] o.s.a.r.l.SimpleMessageListenerContainer : Restarting Consumer: tags=[{}], channel=null, acknowledgeMode=AUTO local queue size=0
完成任務一,耗時:4951毫秒
完成任務二,耗時:7451毫秒
2017-04-28 18:25:42.971 WARN 17848 --- [cTaskExecutor-2] o.s.a.r.l.SimpleMessageListenerContainer : Consumer raised exception, processing can restart if the connection factory supports it. Exception summary: org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused: connect
2017-04-28 18:25:42.972 INFO 17848 --- [cTaskExecutor-2] o.s.a.r.l.SimpleMessageListenerContainer : Restarting Consumer: tags=[{}], channel=null, acknowledgeMode=AUTO local queue size=0
over
相關推薦
Spring @Async實現非同步呼叫示例
什麼是“非同步呼叫”? “非同步呼叫”對應的是“同步呼叫”,同步呼叫指程式按照定義順序依次執行,每一行程式都必須等待上一行程式執行完成之後才能執行;非同步呼叫指程式在順序執行時,不等待非同步呼叫的語句返回結果就執行後面的程式。 同步呼叫 下面通過一個簡單示例來直觀的理解什麼是同步呼叫:
Spring Boot2.0之@Async實現非同步呼叫
補充一個知識點: lombok底層原理使用的是: 位元組碼技術ASM修改位元組碼檔案,生成比如類似於get() set( )方法 一定要在開發工具安裝 在編譯時候修改位元組碼檔案(底層使用位元組碼技術),線上環境使用編譯好的檔案 下面我們學習 Spring Boot 非同步呼
Spring Boot 基礎系列教程 | 第三十二篇:使用@Async實現非同步呼叫:自定義執行緒池
推薦 Spring Boot/Cloud 視訊: 在之前的Spring Boot基礎教程系列中,已經通過《Spring Boot中使用@Async實現非同步呼叫》一文介紹過如何使用@Async註解來實現非同步呼叫了。但是,對於這些非同步執行的控制是我們保障自身
Spring Boot中使用@Async實現非同步呼叫
一 點睛 1 什麼是“非同步呼叫” “非同步呼叫”對應的是“同步呼叫”,同步呼叫指程式按照定義順序依次執行,每一行程式都必須等待上一行程式執行完成之後才能執行;非同步呼叫指程式在順序執行時,不等待非
Spring Boot學習(十二)之Spring Boot使用@Async實現非同步呼叫
什麼是“非同步呼叫”?“非同步呼叫”對應的是“同步呼叫”,同步呼叫指程式按照定義順序依次執行,每一行程式都必須等待上一行程式執行完成之後才能執行;非同步呼叫指程式在順序執行時,不等待非同步呼叫的語句返回
Spring Boot使用@Async實現非同步呼叫返回結果:使用Future以及定義超時
關於使用 @Async實現非同步呼叫的內容,也得到不少童鞋的反饋,其中問題比較多的就是關於返回 Future的使用方法以及對非同步執行的超時控制,所以這篇就來一起講講這兩個問題的處理。 如果您對於 @Async註解的使用還不瞭解的話,可以看看之前的文章,具體如下: 定
springboot乾貨——(十六)使用@Async實現非同步呼叫
非同步呼叫針對的是同步呼叫,一般在程式碼中我們使用同步呼叫相對較多,即請求程式碼立即返回結果或者說執行程式碼,非同步呼叫則是指請求之後不會裡面返回結果或者是呼叫程式碼。 接下來我們用例項來看下什麼是同步呼叫: 新建一個springboot專案後建立對應的task類: pa
SpringBoot之——使用@Async實現非同步呼叫
一、什麼是“非同步呼叫”“非同步呼叫”對應的是“同步呼叫”,同步呼叫指程式按照定義順序依次執行,每一行程式都必須等待上一行程式執行完成之後才能執行;非同步呼叫指程式在順序執行時,不等待非同步呼叫的語句返回結果就執行後面的程式。二、同步呼叫下面通過一個簡單示例來直觀的理解什麼是
如何運用Spring框架的@Async實現非同步任務
在此篇文章中,我們根據使用@Async註解進行探索Spring對非同步執行的支援。簡單的把@As
Spring boot ApplicationEvent實現非同步呼叫
1.什麼是事件機制 事件機制在java的設計模式中也可以叫監聽器模式或者是觀察者模式。 當有事件發生時,通知關注次事件的物件傳送訊息,告訴它有一個事件發生了,那麼怎麼知道通知誰呢? 那必須要在對這個事件感興趣的物件中定義這個事件,一旦有事件發生了,對事件有興
譯文:如何運用Spring框架的@Async實現非同步任務
概要說明 在此篇文章中,我們根據使用@Async註解進行探索Spring對非同步執行的支援。 簡單的把@Async註解放到Bean的方法上就會使用不同的執行緒執行,也就是說,呼叫者執行此方法不用一直等待整個方法執行完畢。 在Spring中比較有趣的一點就是
spring使用Async實現非同步或者延遲的操作
對於我們的web專案,一般來說,我們都是同步執行一些資料,所謂同步就是按照順序,執行完這個然後有序的執行下一個,但是有時我們需要延遲執行一些資料,並且這些資料我們不需要實時的返回的,比如是註冊成功,我們會返回一封郵件給使用者,這個郵件我們可以在使用者註冊成功後的5分鐘,或者10分鐘後向使用者傳送,那麼我們就
java實現非同步呼叫例項
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
spring+mq實現非同步處理
最近研究了一下spring/spring boot與activeMq的整合,花費了很多時間,也遇到了很多坑,工作之餘,總結一下。 業務邏輯是這樣的,有一個功能(比如使用者註冊)執行十分緩慢,但是實際需要發起請求之後馬上提示“處理成功”而不關心是否真的處理成功,這種情況就可以交給MQ來處理
Java 實現非同步呼叫
首先 我遇到的問題是 介面呼叫時需要更新快取 而更新快取又是個說快不快的過程 所以打算做非同步呼叫 返回我所需要的結果即可 ,至於快取什麼時候更新完 就不是我所需要關注的了廢話不多說 上程式碼public class MyExecutor { private Execu
Java多執行緒實現非同步呼叫
在JAVA平臺,實現非同步呼叫的角色有如下三個角色:呼叫者 提貨單 真實資料 一個呼叫者在呼叫耗時操作,不能立即返回資料時,先返回一個提貨單.然後在過一斷時間後憑提貨單來獲取真正的資料. 去蛋糕店買蛋糕,不需要等蛋糕做出來(假設現做要很長時間),只需要領個提貨單就可以了(去幹別的事情),等到蛋糕做好
使用 RabbitMQ 實現非同步呼叫
目錄 引言 啟動 RabbitMQ 伺服器 執行 rabbitmq 容器 RabbitMQ 控制檯 Exchange 和 Queue 開發服務端和客戶端 開發服務端 開發客戶端 Java Bean 型別傳輸 結語
c#使用委託實現非同步呼叫
非同步程式設計是受公共語言執行庫的許多領域(如遠端處理、ASP.NET 和 Windows 窗體)支援的功能。非同步程式設計是 .NET Framework 中的核心概念。使用 .NET 非同步程式設計,在程式繼續執行的同時對 .NET 類方法進行呼叫,直到進行指定的回撥為止
從Java future 到 Guava ListenableFuture實現非同步呼叫
前言 隨著移動網際網路的蓬勃發展,手機App層出不窮,其業務也隨之變得錯綜複雜。針對於開發人員來說,可能之前的一個業務只需要調取一次第三方介面以獲取資料,而如今隨著需求的增加,該業務需調取多個不同的第三方介面。通常,我們處理方法是讓程式碼
CXF整合spring框架實現動態呼叫,找不到函式介面, 新增攔截器無法初始化
介面實現 新增targetNamespace客戶端就不會找不到函式 @WebService(endpointInterface="cn.com.wsws.server.SealService",se