Migración de aplicaciones que utilizan modelos de programación de simultaneidad y asíncronos a Liberty
Se pueden migrar aplicaciones que usen Concurrency Utilities for Java™ EE, beans asíncronos y un gestor de trabajo y temporizador CommonJ de WebSphere Application Server tradicional a WebSphere Application Server Liberty.
Los beans asíncronos y CommonJ Timer y Work Manager no están disponibles en Liberty. Cuando se migra a Liberty, las aplicaciones deben cambiar al modelo de programación de Concurrency Utilities for Java EE. Para obtener más información, consulte Tareas de API de ejemplo que implementan Concurrency Utilities for Java EE.
Diferencias en la configuración y la generación de hebras
WebSphere Application Server tradicional proporciona una serie de opciones de configuración de Concurrency Utilities for Java EE relacionadas con la agrupación de hilos que se configuran de manera distinta o no están disponibles en Liberty. Liberty tiene una sola agrupación de hebras común entre todos los ejecutores gestionados y los ejecutores planificados gestionados que también comparten los componentes de Liberty. Esto permite a Liberty optimizar la gestión de hebras. En WebSphere Application Server tradicional, cada gestor de trabajo puede configurarse con dos agrupaciones de hilos. Una agrupación de hebras es para las tareas que se envían para ejecutarse lo antes posible (métodos submit/execute/invoke del ejecutor gestionado) y tiene una cola de solicitudes de trabajo configurable y una acción para realizar cuando se excede la capacidad de la cola. La otra agrupación de hebras es para tareas planificadas (métodos de planificación del ejecutor planificado gestionado).
Si tiene previsto usar Concurrency Utilities for Java EE con agrupaciones de hilos independientes en Liberty, se pueden adoptar diversos enfoques para lograr un comportamiento similar al de las opciones de configuración disponibles en WebSphere Application Server tradicional.
![[17.0.0.4 and later]](../ng_v17004plus.gif)
Uso de la configuración de políticas de concurrencia
La configuración concurrencyPolicy no se aplica a las tareas planificadas.La tabla siguiente lista las opciones de configuración disponibles al elemento concurrencyPolicy y cómo se compara dicho elemento con WebSphere Application Server tradicional. La configuración concurrencyPolicy no se aplica a las tareas planificadas.
concurrencyPolicy de ejecutores gestionados de Liberty | Gestor de trabajo y ejecutores gestionados de WebSphere Application Server tradicional |
---|---|
max | Máximo de hilos |
maxQueueSize | Tamaño de la cola de solicitudes de trabajo |
maxWaitForEnqueue | Acción plena de la cola de solicitudes de trabajo = WAIT |
runIfQueueFull = false | Acción plena de la cola de solicitudes de trabajo = FAIL |
startTimeout | Tiempo de espera de inicio |
longRunningPolicyRef + longrunning hint | Trabajo de demonio |
El elemento expedite es igual al objetivo de mínimo de hilos que se despachan en la agrupación de hilos global de Liberty en lugar de un número fijo de mínimo de hilos.
Construcción de un ejecutor Java SE en una fábrica de hebras gestionadas
El paquete java.util.concurrent de Java SE proporciona varias formas de construir agrupaciones de hebras como ejecutores y ejecutores planificados en una fábrica de hebras específica. Se puede proporciona una fábrica de hebras gestionadas en lugar de una fábrica de hebras no gestionadas, lo que genera una agrupación de hebras que ejecuta tareas en hebras gestionadas. A diferencia del ejecutor gestionado y los ejecutores planificados gestionados, las hebras gestionadas agrupadas por estos ejecutores se ejecutan con el contexto de hebras desde el que se buscó la fábrica de hebras gestionadas, no desde el que se envió o planificó la tarea. El contexto de hebras también permanece en la hebra gestionado durante la vida de la hebra, lo que reduce la sobrecarga de la conmutación del contexto de hebras.
![[17.0.0.4 and later]](../ng_v17004plus.gif)
Ejemplo de sustitución para un máximo de hebras de trabajo y una configuración de cola de trabajos
<managedExecutorService jndiName="concurrent/execSvc">
<concurrencyPolicy max="2" maxQueueSize="3" runIfQueueFull="false" maxWaitForEnqueue="0"/>
</managedExecutorService>
Ejemplo de sustitución para máximo de hebras de alarma
int maxAlarms = 2;
ManagedThreadFactory threadFactory =
(ManagedThreadFactory) new InitialContext().lookup(
"java:comp/DefaultManagedThreadFactory");
ScheduledExecutorService executor =
Executors.newScheduledThreadPool(maxAlarms, threadFactory);
Callable<Integer> task = new MyTask();
ScheduledFuture<Integer> future = executor.schedule(
task, 50, TimeUnit.SECONDS);
int result = future.get();
![[17.0.0.4 and later]](../ng_v17004plus.gif)
Aplicación de un tiempo de espera de inicio
<managedExecutorService jndiName="concurrent/execSvc">
<concurrencyPolicy startTimeout="1m"/>
</managedExecutorService>
Aplicación de un tiempo de espera de trabajo
Use WebSphere Application Server tradicional para configurar un tiempo de espera de trabajo que se aplique a las tareas enviadas para ejecutar tan pronto como sea posible (métodos submit/execute/invoke). Si una tarea se ejecuta durante un tiempo superior al tiempo de espera de trabajo asignado, el programa intentará cancelarla interrumpiéndola. Liberty no tiene el tiempo de espera de trabajo como opción de configuración, pero se puede implementar un comportamiento similar enviando la tarea con un escucha de tarea gestionada. En respuesta a la notificación taskStarting, el escucha de la tarea gestionada planifica una tarea para cancelar el método Future. De forma alternativa, cuando se utiliza un ejecutor de agrupación de hilos donde no está disponible un escucha de tarea gestionada, se puede sustituir el método beforeExecute del ejecutor de agrupación de hilos para planificar una tarea que interrumpa el hilo de ejecución.
Ejemplo de sustitución para tiempo de espera de trabajo
ManagedExecutorService executor =
(ManagedExecutorService) new InitialContext().lookup(
"java:comp/DefaultManagedExecutorService");
Callable<Long> slowTask = new SlowTask();
slowTask = ManagedExecutors.managedTask(
slowTask, new WorkTimeout(5, TimeUnit.SECONDS));
Future<Long> future = executor.submit(slowTask);
try {
long result = future.get(1, TimeUnit.MINUTES);
// tarea satisfactoria...
} catch (CancellationException x) {
// la tarea se ha cancelado, posiblemente debido a un tiempo de espera
}
public class WorkTimeout implements ManagedTaskListener {
private final long timeout;
private final TimeUnit unit;
public WorkTimeout(long timeout, TimeUnit unit) {
this.timeout = timeout;
this.unit = unit;
}
public void taskSubmitted(Future<?> future,
ManagedExecutorService executor, Object task) {}
public void taskStarting(final Future<?> future,
ManagedExecutorService executor, Object task) {
try {
ScheduledExecutorService scheduledExecutor =
(ScheduledExecutorService) new InitialContext().lookup(
"java:comp/DefaultManagedScheduledExecutorService");
scheduledExecutor.schedule(new Runnable() {
@Override
public void run() {
if (!future.isDone())
future.cancel(true);
}
}, timeout, unit);
} catch (NamingException x) {
x.printStackTrace(System.out);
}
}
public void taskAborted(Future<?> future, ManagedExecutorService executor, Object task, Throwable x) {}
public void taskDone(Future<?> future, ManagedExecutorService executor, Object task, Throwable x) {}
}
![[17.0.0.4 and later]](../ng_v17004plus.gif)
Ejemplo de trabajo de demonio
Configuración:
<concurrencyPolicy id="longRunning" max="2"/>
<managedExecutorService jndiName="concurrent/execSvc" longRunningPolicyRef="longRunning" />
Código de aplicación
ManagedExecutorService executor =
(ManagedExecutorService) new InitialContext().lookup(
"concurrent/execSvc");
Map<String, String> props = Collections.singletonMap(ManagedTask.LONGRUNNING_HINT,
Boolean.TRUE.toString());
Callable<Long> slowTask = ManagedExecutors.managedTask(new SlowTask(), props, null);
Future<Long> future = executor.submit(slowTask);