2016-11-22 97 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。这两个子系统有他们自己独特的线程池,他们利用。

相关问题