2016-11-22 96 views
3

我工作在java web應用程序的後端。我添加了一些多線程來加速大數據檢索,並且我使用了一些在此過程中創建的ExecutorServices。不過,我已經讀過,在Web應用程序中以這種方式創建線程可能不是一個好主意,並且'com.ibm.websphere.asynchbeans.WorkManager'也許是一個選項。儘管如此,在後端使用似乎不是很友好。根據文檔,工作管理器是爲使用異步Bean的Java平臺企業版(Java EE)應用程序創建的「線程池」。我作爲一個非常前端無知的後端傢伙,甚至都不知道豆子是什麼。看起來工作管理器並不是我想要的,但如果手動創建ExecutorService實際上是一個壞主意,我不確定最佳方法是什麼。我應該在後端(java)中使用WorkManager進行多線程嗎?

+0

我會建議創建一個單獨的類,它將有一個Executor服務,並在池中有一個固定數量的線程,比如說10.每次創建一個線程時,調用這個單例類並將任務傳遞給這個執行者服務來執行它。這樣你就不會創建大量的線程池,而是共享一個線程池。 –

+0

此外,您可以輪詢當前的系統規格/容量,並配置此Threadpool/Singleton執行器以優化性能。 – n247s

+0

@ BandiKishore,@ n247s我認爲OP詢問在一般情況下在Web容器中創建線程是否是一種好的做法。 –

回答

3

在webapp的後端創建自己的線程是一個壞主意,原因如下:Application Server容器爲您管理線程。所以如果你在你的應用程序中創建自己的線程,容器將不知道它們,並且將無法管理它們。因此,如果你管理不當,你的應用程序可能導致內存泄漏和其他線程相關的問題。從理論上講,最好的方法是在App Server中註冊一些線程池,並使用JNDI從容器中請求線程。但它可能是一個矯枉過正的問題。所以有時候,你可能想要管理你自己的線程。所以,在這種情況下ExecutorService是最好的方式,因爲它提供了非常好的API來管理你的線程。只要確保在應用程序關閉時關閉ExecutorService即可,因此不會留下孤立線程。如果你對此非常小心,那麼你可以創建自己的線程。請謹慎使用它們,並且小心您在完成或關閉應用程序時關閉了ExecutorService。順便說一句,有ThreadLocal變量類似的問題。完成後,您絕對必須在其中調用metod remove(),否則即使您的應用程序已關閉,它們仍會保留在內存中,並且只有Application Server重新啓動才能清除它們。這是一個危險的內存泄漏。

1

只是爲了邁克爾Gantman的答案,這是一個相當不錯的解釋,JavaEE的方法來使容器管理線程池是超級容易真正實現擴大:

@Stateless 
public class Foo { 

    @Asynchronous 
    @Override 
    public void doSomething() { 
     //all calls to this function are asynchronous 
    } 
} 

@Aysnchronous需要的魔法護理在這裏,向容器指定這個函數應該被異步調用,容器的責任是弄清楚它的含義。然後呼喚你的容器管理線程池來執行你的功能很簡單,只要:

@Stateless 
public class Bar { 
    @EJB 
    Foo myFooEJB; 

    public void businessMethod() { 
     myFooEJB.doSomething(); 
    } 
} 

結帳這些更多閱讀:javax.ejb.AsynchronousAsynchronous method invocation。獲取也許有點太成細節,因爲我知道你正在使用IBM的產品,在JBoss中,你的異步是作爲一個子系統配置的一部分,通過指定<async thread-pool-name="poolName"/>https://docs.jboss.org/author/display/WFLY8/EE+Subsystem+Configuration) 其中poolName應該引用池如:

<thread-pools> 
    <thread-pool name="poolName"> 
     <max-threads count="10"/> 
     <keepalive-time time="100" unit="milliseconds"/> 
    </thread-pool> 
</thread-pools> 

但還有如果你想提交,只是一些任務的ExecutorService可以由容器來管理一個更好的方法:

@Resource 
ManagedExecutorService executorService; 

@Resource 
ManagedScheduledExecutorService scheduledExecutorService; 

java.io.PrintWriter out = ...; 

void scheduleSomeStuff(){ 
    scheduledExecutorService.schedule(new Runnable() { 
     @Override 
     public void run() { 
      out.println("Print out after roughly 15 seconds.") 
     } 
    }, 15, TimeUnit.SECONDS); 

    executorService.submit(new Callable<Boolean>() { 
     @Override 
     public Boolean call() throws Exception { 
      out.println("Print only once, when the task is run by the executor service's discretion."); 
     } 
    }; 
} 

這兩種資源,特別是我在這裏已經參考,運行在不同的線程池中。在這之前,我原本在這裏發佈了一些使用@Asynchronous線程池作爲執行程序的東西,但沒有必要,因爲容器應該已經有一個給你;因此您現在在這裏看到更新的答案。

這也可能是JBoss的一個小特性,但在JBoss中,它被配置爲子系統managed-scheduled-executor-servicesmanaged-executor-services。這兩個子系統有他們自己獨特的線程池,他們利用。

相關問題