2014-01-22 16 views
1

我們想優化我們的應用程序。有一些線性的線性工作正在進行,可以用更小的工​​作集在多個線程中執行。CDI多線程

我們的典型服務使用我們的CDI託管的豆中的@Inject註釋進行訪問。而且,這種服務可以有它自己的依賴注入,即:

public class MyService { 

    @Inject 
    private OtherService otherService; 

    @Inject 
    private DataService1 dataService1; 

    ... 

    public void doSomething() { 
    ... 
    } 
} 

因爲我不能用@Inject實現Runnable裏面的類。 (它不是容器管理的。)我嘗試在啓動線程之前將所需的服務傳遞給類。因此,使用這樣的事情,使得服務實例(myService)內螺紋可供選擇:

Class Thread1 implements Runnable{ 
    private MyService myService 

    public Thread1(MyService myService){ 
     this.myService = myService; 
    } 

    public void run(){ 
     myService.doSomething(); 
    } 
} 

繼呼叫層次調用doStometing()是好的,因爲myService參考已經過去了。就我所瞭解的CDI而言,注射是在屬性第一次被訪問的那一刻完成的,也就是說,當doStomething()方法試圖訪問otherServicedataService1時,將執行注入。

但是,在這一點上,我收到一個例外,沒有可用的上下文。

我也嘗試使用JBossThreadExecuter類而不是Plain-Threads - 它導致了相同的結果。

所以問題是,如果有一種很好的方式將上下文(或請求)與創建的Thread關聯?

對於EJB-Beans,我讀到標記爲@Asynchronous的方法將導致該方法在託管線程中運行,該線程本身將連接到上下文。這基本上就是我正在尋找的東西。

有沒有辦法在CDI中做到這一點?

或者有什麼方法可以從非託管線程中獲得context

+0

注入的服務及其依賴關係的範圍是什麼? –

+0

@JohnAment大部分都是'@ Stateless'。有些是'@ RequestScoped'。 – dognose

回答

4

焊接允許通過程序上下文管理,(there's an example in the official docs).

但是你走這條路給EJB的機會)之前
@Async調用功能,這正是你的情況。作爲獎勵,您將獲得超時截聽和交易管理。

+0

加上異步調用發生在來自可配置線程池的線程中,這使預測和監視線程行爲變得更容易。 – Yuri

3

當您啓動異步過程時,您的@RequestScoped@SessionScoped對象不再處於範圍內。這就是爲什麼你會注入@RequestScoped對象的分辨率錯誤。在沒有CDI範圍的情況下使用@Stateless基本上是@Dependent。您可以使用@ApplicationScoped對象,或者如果您使用的是CDI 1.1,則可以啓動@TransactionScoped

0

您必須使用JavaEE 7功能,託管執行程序。所以它會爲你的可運行提供一個上下文。我不確定您的JBoss版本是否與JavaEE 7兼容。至少Glassfish 4是,並且這種方法有效。 查看詳情here

0

可以想到的最簡單的解決方案是Ejb異步。

它們功能強大,工作正常,最重要的是併發由容器處理(如果未正確管理,可能會在某個時間點出現問題)。

只是一個簡單的用例可以說,如果我們已經編寫了一個rest服務,並且每個請求都會產生10個線程(例如使用CompletableFuture或任何其他)來執行一些長處理任務,並且如果有500個請求被創建,那麼線程被管理,應用程序的行爲如何,它是否等待線程池中的線程,什麼是超時時間等等,並增加我們的舒適度當線程是Deamon線程時會發生什麼。我們可以在一定程度上使用EJB來避免這些開銷。

從技術服務團隊獲得一位朋友來幫助我們處理所有這些容器的具體實現總是一件好事。