2017-05-30 114 views
0

我在我的代碼中使用了@Async從Rest控制器向3個不同的方法進行3個並行調用。
線程管理/ Spring的工作@Async

根據我對servlet的理解(這可能是錯誤的),當Spring彈出@RestController方法收到一個請求時,爲它創建一個線程,從此以後爲每個新請求創建一個新線程。

請求線程1 - 3異步線程創建
請求線程2 - 3個異步線程創建

現在怎麼春/請求的線程知道3異步線程屬於哪個哪個線程即請求線程1或請求線程2.

可能有某種映射告訴他們。
我試過在網上搜索@Async,但其工作中很少有文檔可用。谷歌充斥着如何使用代碼但沒有運作。

底線 - 有人可以解釋我的@Async代碼


更新與圖像的工作/線程管理更好的解釋:

enter image description here

1)請求1進來,產卵3線程(A1,A2,& A3),因爲它是一個帶有響應R1,R2 & R3的異步調用。
2)請2進來&做同樣的事情,即要求:A4,A5 A6 &與響應,R1,R2 R3 & ..
3)現在的問題是如何R1,R2 R3 &意識到自己部分相同的請求,即請求1.如果它將是一個順序調用,那麼同一個線程將從頭到尾傳播。但創建6 Async請求後,我只能看到線程轉儲中只有6個線程,並且沒有線程作爲請求1或請求2。
那麼R1和R2的完成如何完成請求1完成但尚未完成的R1,R2 & R6誰&哪裏是記錄保持請求1是從R1完成的,R2 & R3。

+1

'@ ASync'總之不做任何事情,它是一個註釋。如果沒有'@ EnableAsync',它也不會執行任何操作。另外它的工作方式和工作方式取決於你的'TaskExecutor'。你對'@ RestController'的理解是錯誤的,沒有創建線程,實際上默認的servlet行爲是阻塞的,並使用線程池中的線程(取決於你的servlet容器)。它是異步的,所以只要方法已經發出,你的控制器就會返回(除非你正在返回'Future'並且調用'get',這使得它成爲阻塞調用,再次擊敗了@ @ Async'的目的)。 –

+0

任務執行程序只是線程的一種方式,即從池中重用,或爲每個請求創建和銷燬。當我爲每個請求說新的線程時,我的意思是每個請求都在不同的線程中處理,如果從線程池創建或挑選它,則無關緊要。此外,我不關心阻塞性質,我認爲.isDone標誌在這裏有點。我的問題是如何創建3個異步線程(即總共6個)的2個不同請求返回到它們原始的調用線程 –

+0

如通常所說的,除非您使用'Future'或'CompletableFuture'並使用'get'將使其基本上再次同步調用(請求處理線程將阻塞,直到進程完成)如果您不使用這種機制,他們只是不等待並立即返回。來自控制器 –

回答

0

例如,讓我們的findUser方法從Spring's tutorial

@Async 
public CompletableFuture<User> findUser(String user) throws InterruptedException { 
    logger.info("Looking up " + user); 
    String url = String.format("https://api.github.com/users/%s", user); 
    User results = restTemplate.getForObject(url, User.class); 
    // Artificial delay of 1s for demonstration purposes 
    Thread.sleep(1000L); 
    return CompletableFuture.completedFuture(results); 
} 

假設你正在使用@EnableAsync,每次調用findUser實際上調用代理:

  1. 創建CompletableFuture實例。
  2. 在不同的線程中執行findUser,傳遞相同的CompletableFuture實例。
    • 一旦執行完成,它將更新共享的CompletableFuture實例。
  3. 向調用者返回CompletableFuture

線程池在你的程序中,從該代理需要線程來運行你的代碼的開頭創建的。


The implementation是在AsyncExecutionInterceptor類,invoke方法。