简体   繁体   English

Jboss Java EE容器和ExecutorService

[英]Jboss Java EE container and an ExecutorService

I have a standalone java app which used the ExecutorService to process a number of jobs in parallel 我有一个独立的Java应用程序,它使用ExecutorService并行处理大量作业

 ExecutorService es = Executors.newFixedThreadPool(10);

I now want to re-use the same solution within an EJB bean but am unsure how to correctly initialize the ThreadPool, since I'd normally leave the Java EE container to control all thread resources. 我现在想在EJB bean中重用相同的解决方案但不确定如何正确初始化ThreadPool,因为我通常会让Java EE容器控制所有线程资源。 Can I just use the same code or is there an alternative correct way to get a Jboss managed thread pool? 我可以使用相同的代码,还是有另一种正确的方法来获取Jboss托管线程池?

The correct way to do this in your EJB is to use the ManagedExecutorService, which is part of the Concurrency Utils API (Java EE7). 在EJB中执行此操作的正确方法是使用ManagedExecutorService,它是Concurrency Utils API(Java EE7)的一部分。 You shouldn't be using any ExecutorService that is part of the java.util.concurrent in your enterprise code. 您不应该使用属于企业代码中java.util.concurrent的任何ExecutorService。

By using the ManagedExecutorService your new thread will be created and managed by the container. 通过使用ManagedExecutorService,您的新线程将由容器创建和管理。

The following example is taken from my site here . 下面的例子是从我的网站采取了这里

To create a new thread using a ManagedExecutorService, first create a task object that implements Callable. 要使用ManagedExecutorService创建新线程,首先要创建一个实现Callable的任务对象。 Within the call() method we will define the work that we want carried out in a separate thread. 在call()方法中,我们将定义我们想要在单独的线程中执行的工作。

public class ReportTask implements Callable<Report> {

    Logger logger = Logger.getLogger(getClass().getSimpleName());

    public Report call() {
        try {
            Thread.sleep(3000);
        catch (InterruptedException e) {
            logger.log(Level.SEVERE, "Thread interrupted", e);
        }
        return new Report();
    }
}

Then we need to invoke the task by passing it though to the submit() method of the ManagedExecutorService. 然后我们需要通过将任务传递给ManagedExecutorService的submit()方法来调用该任务。

@Stateless
public class ReportBean {

    @Resource
    private ManagedExecutorService executorService;

    public void runReports() {
        ReportTask reportTask = new ReportTask();
        Future<Report> future = executorService.submit(reportTask);
    }
}

Obligatory warning: Creating your own threads in a Java EE app server (even Tomcat) is discouraged as it can be a huge performance issue and in most cases will prevent container functionality, such as JNDI, from working. 强制警告:不鼓励在Java EE应用服务器(甚至Tomcat)中创建自己的线程,因为它可能是一个巨大的性能问题,并且在大多数情况下会阻止容器功能(如JNDI)工作。 The new threads won't know which application they belong to, the Thread context classloader will not be set and many other hidden issues. 新线程将不知道它们属于哪个应用程序,不会设置Thread上下文类加载器以及许多其他隐藏的问题。

Fortunately there is a way to get the Java EE server to manage the thread pool via the Java EE 6 @Asynchronous and this clever design pattern. 幸运的是,有一种方法可以让Java EE服务器通过Java EE 6 @Asynchronous和这种聪明的设计模式来管理线程池。 Portable to any Java EE 6 certified server. 可移植到任何Java EE 6认证的服务器。

Create this EJB in your application. 在您的应用程序中创建此EJB。

package org.superbiz;

import javax.ejb.Asynchronous;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;

@Stateless(name="Executor")
public class ExecutorBean implements Executor {

    @Asynchronous
    @Override
    public void execute(Runnable command) {
        command.run();
    }
}

Then you can refer to this bean elsewhere in your application via plain dependency injection (if the referring component is a Servlet, Listener, Filter, other EJB, JSF Managed bean). 然后,您可以通过普通依赖注入(如果引用组件是Servlet,Listener,Filter,其他EJB,JSF Managed bean)在您的应用程序的其他位置引用此bean。

@EJB
private Executor executor;

Then use the Executor as normal. 然后像往常一样使用Executor

If the component is not another Java EE component, you can lookup the bean via: 如果组件不是另一个Java EE组件,则可以通过以下方式查找bean:

InitialContext initialContext = new InitialContext();
Executor executor = (Executor) initialContext.lookup("java:module/Executor");

Well... David's solution did not work for me for the following reasons: 嗯......大卫的解决方案对我不起作用,原因如下:

  1. Compiler was bitching around that java.util.concurrent is not allowed... which kinda makes sense in JBOSS scope. 编译器喋喋不休地说java.util.concurrent是不允许的......在JBOSS范围内哪种方式有意义。
  2. Also: public STATIC class...? 另外:公共STATIC课......? Read this up: Why are you not able to declare a class as static in Java? 阅读本文: 为什么你不能在Java中将类声明为静态?

Here's what I did: 这是我做的:
My installation: 我的安装:
- JBOSS AS 7.1.1 - JBOSS AS 7.1.1
- Java 1.6 - Java 1.6
- RHEL - RHEL
- Running the example with Gradle and Arquillian : - 使用GradleArquillian运行示例:

@Stateless
public class ExecutorBean {
    @Asynchronous
    public void execute(Runnable command) {
        command.run();    
    }
}

Then your client looks like this: 然后你的客户端看起来像这样:

@EJB ExecutorBean eb;
@Test
public void testExecutorBean() {
    eb.execute(new YourCustomizedRunnableWhichDoesALotOfUsefulStuff());
    assertFalse(!true);
}

Beware, though: In my standalone.xml (or generally speaking my config file for JBOSS I have a section 'thread-pools'. Have a look at it (if you happen to use JBOSSAS) and tinker with the values there. Find out how it behaves. When I use threads with arquillian tests I get threads that are killed though my keepalive-time is very high. I think this has to do with how arquillian microdeploys. When arquillian finishes all non-finished threads are killed which were running whilst the tests are being run... at least that is what I think I observe. On the other hand all finished threads actually behaved well in that sense that they completed their tasks/operations. 但请注意:在我的standalone.xml中(或者一般来说我的JBOSS配置文件中有一个'线程池'部分。看看它(如果你碰巧使用JBOSSAS)并修改那里的值。找出来它是如何表现的。当我使用带有arquillian测试的线程时,我得到的线程虽然我的保持时间非常高但已被杀死。我认为这与arquillian microdeploys有关。当arquillian完成所有未完成的线程被杀死时正在运行测试正在进行中......至少这是我认为我观察到的。另一方面,所有完成的线程实际上表现得很好,他们完成了任务/操作。

Hope this post helps! 希望这篇文章有帮助!

Prior to EE7, you might want to use WorkManager from JSR 237 在EE7之前,您可能希望使用JSR 237中的WorkManager

http://docs.oracle.com/javaee/1.4/api/javax/resource/spi/work/WorkManager.html http://docs.oracle.com/javaee/1.4/api/javax/resource/spi/work/WorkManager.html

This spec is currently withdrawn, still some app servers implement it. 此规范目前已撤销,仍有一些应用服务器实现它。 I use ibm implementation in WebSphere 8.5 - IBM WorkManager . 我在WebSphere 8.5中使用ibm实现 - IBM WorkManager It is fully managed resource, available in administration console. 它是完全托管的资源,可在管理控制台中使用。 Please note that it is not interface-compatible with Oracle. 请注意,它与Oracle不兼容。

Here is an example for IBM version: 以下是IBM版本的示例:

@Resource(lookup = "wm/default")
WorkManager workManager;

public void process() {
    try {
        ArrayList<WorkItem> workItems = new ArrayList<WorkItem>();
        for (int i = 0; i < 100; i++) {
            // submit 100 jobs
            workItems.add(workManager.startWork(new Work() {
                @Override
                public void run() {
                    try {
                        System.out.println(Thread.currentThread().getName() + " Running");
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void release() {
                    System.out.println(Thread.currentThread().getName() + " Released");
                }
            }));
        }
        // wait for all jobs to be done.
        workManager.join(workItems, WorkManager.JOIN_AND, 100000);
    } catch (WorkException e) {
        e.printStackTrace();
    }
}

Also I am aware of Commonj Workmanager . 我也知道Commonj Workmanager

If you are using JBoss, you can use org.jboss.seam.async.ThreadPoolDispatcher. 如果您使用的是JBoss,则可以使用org.jboss.seam.async.ThreadPoolDispatcher。

ThreadPoolDispatcher is completely managed. ThreadPoolDispatcher是完全托管的。

For others useful managed classes, see the package: org.jboss.seam.async. 对于其他有用的托管类,请参阅包:org.jboss.seam.async。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM