Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

 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. Can I just use the same code or is there an alternative correct way to get a Jboss managed thread pool?

like image 973
emeraldjava Avatar asked Dec 18 '12 11:12

emeraldjava


People also ask

What is Java ExecutorService?

The Java ExecutorService is a construct that allows you to pass a task to be executed by a thread asynchronously. The executor service creates and maintains a reusable pool of threads for executing submitted tasks.

Why ExecutorService is used in Java?

The ExecutorService helps in maintaining a pool of threads and assigns them tasks. It also provides the facility to queue up tasks until there is a free thread available if the number of tasks is more than the threads available.

What is ExecutorService and how its works?

ExecutorService is a JDK API that simplifies running tasks in asynchronous mode. Generally speaking, ExecutorService automatically provides a pool of threads and an API for assigning tasks to it.

Can you give an example for ExecutorService?

Here is an example of executing a Runnable with an ExecutorService : ExecutorService executorService = Executors. newSingleThreadExecutor(); executorService. execute(new Runnable() { public void run() { System.


2 Answers

The correct way to do this in your EJB is to use the ManagedExecutorService, which is part of the Concurrency Utils API (Java EE7). You shouldn't be using any ExecutorService that is part of the java.util.concurrent in your enterprise code.

By using the ManagedExecutorService your new thread will be created and managed by the container.

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. Within the call() method we will define the work that we want carried out in a separate thread.

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.

@Stateless public class ReportBean {      @Resource     private ManagedExecutorService executorService;      public void runReports() {         ReportTask reportTask = new ReportTask();         Future<Report> future = executorService.submit(reportTask);     } } 
like image 175
Chris Ritchie Avatar answered Sep 22 '22 02:09

Chris Ritchie


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. The new threads won't know which application they belong to, the Thread context classloader will not be set and many other hidden issues.

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. Portable to any Java EE 6 certified server.

Create this EJB in your application.

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).

@EJB private Executor executor; 

Then use the Executor as normal.

If the component is not another Java EE component, you can lookup the bean via:

InitialContext initialContext = new InitialContext(); Executor executor = (Executor) initialContext.lookup("java:module/Executor"); 
like image 38
David Blevins Avatar answered Sep 22 '22 02:09

David Blevins