Contenedor Jboss Java EE y un ExecutorService

Tengo una aplicación java independiente que utiliza el ExecutorService para procesar varios trabajos en paralelo

ExecutorService es = Executors.newFixedThreadPool(10); 

Ahora quiero volver a utilizar la misma solución dentro de un bean EJB pero no estoy seguro de cómo inicializar correctamente el ThreadPool, ya que normalmente dejaría el contenedor Java EE para controlar todos los recursos de subprocesos. ¿Puedo usar el mismo código o hay una forma alternativa correcta de obtener un grupo de hilos administrados de Jboss?

La forma correcta de hacerlo en su EJB es usar ManagedExecutorService, que es parte de la API de Concurrency Utils (Java EE7). No debe utilizar ningún ExecutorService que sea parte de java.util.concurrent en su código de empresa.

Al usar ManagedExecutorService, su nuevo hilo será creado y administrado por el contenedor.

El siguiente ejemplo se toma de mi sitio aquí .

Para crear un nuevo hilo usando un ManagedExecutorService, primero cree un objeto de tarea que implemente Callable. Dentro del método call () definiremos el trabajo que queremos llevar a cabo en un hilo separado.

 public class ReportTask implements Callable { 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(); } } 

Luego, debemos invocar la tarea pasándola al método submit () del ManagedExecutorService.

 @Stateless public class ReportBean { @Resource private ManagedExecutorService executorService; public void runReports() { ReportTask reportTask = new ReportTask(); Future future = executorService.submit(reportTask); } } 

Advertencia obligatoria: no se recomienda crear sus propios hilos en un servidor de aplicaciones Java EE (incluso Tomcat) ya que puede ser un gran problema de rendimiento y en la mayoría de los casos evitará que la funcionalidad del contenedor, como JNDI, funcione. Los nuevos subprocesos no sabrán a qué aplicación pertenecen, el cargador de clases de contexto de subproceso no se establecerá y muchos otros problemas ocultos.

Afortunadamente, hay una forma de lograr que el servidor Java EE administre el grupo de subprocesos mediante Java EE 6 @Asynchronous y este inteligente patrón de diseño. Portátil para cualquier servidor certificado Java EE 6.

Crea este EJB en tu aplicación.

 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(); } } 

Luego puede consultar este bean en otra parte de su aplicación a través de dependency injection simple (si el componente de referencia es un servlet, un oyente, un filtro, otro EJB, un bean gestionado por JSF).

 @EJB private Executor executor; 

Luego usa el Executor como es normal.

Si el componente no es otro componente de Java EE, puede buscar el bean a través de:

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

Bueno … la solución de David no funcionó para mí por las siguientes razones:

  1. El comstackdor se quejaba de que java.util.concurrent no está permitido … lo cual tiene sentido en el scope de JBOSS.
  2. También: clase STATIC pública …? Lea esto: ¿Por qué no puede declarar una clase como estática en Java?

Esto es lo que hice:
Mi instalación:
– JBOSS AS 7.1.1
– Java 1.6
– RHEL
– Ejecutando el ejemplo con Gradle y Arquillian :

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

Entonces su cliente se ve así:

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

Sin embargo, ten cuidado: en mi standalone.xml (o en general mi archivo de configuración para JBOSS tengo una sección ‘thread-pools’. Echa un vistazo (si usas JBOSSAS) y juega con los valores allí. cómo se comporta. Cuando uso hilos con pruebas arquillianas obtengo hilos que mueren aunque mi tiempo de keepalive es muy alto. Creo que esto tiene que ver con cómo microdesplegar arquillian. Cuando arquillian termina todos los hilos no acabados se matan que se estaban ejecutando mientras las pruebas se están ejecutando … al menos eso es lo que creo que observo. Por otro lado, todos los hilos terminados se comportaron bien en ese sentido en que completaron sus tareas / operaciones.

Espero que esta publicación ayude!

Antes de EE7, es posible que desee utilizar WorkManager desde JSR 237

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

Esta especificación está actualmente retirada, aún algunos servidores de aplicaciones la implementan. Uso la implementación de ibm en WebSphere 8.5 – IBM WorkManager . Es un recurso totalmente administrado, disponible en la consola de administración. Tenga en cuenta que no es compatible con Oracle.

Aquí hay un ejemplo para la versión de IBM:

 @Resource(lookup = "wm/default") WorkManager workManager; public void process() { try { ArrayList workItems = new ArrayList(); 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(); } } 

También estoy al tanto de Commonj Workmanager .

Si está utilizando JBoss, puede usar org.jboss.seam.async.ThreadPoolDispatcher.

ThreadPoolDispatcher está completamente administrado.

Para otras clases administradas útiles, vea el paquete: org.jboss.seam.async.