Migración de aplicaciones que utilizan modelos de programación de simultaneidad y asíncronos a Liberty
Puede migrar aplicaciones que utilizan Concurrency Utilities for Java™ EE, beans asíncronos y CommonJ Timer y Work Manager del 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 para Concurrency Utilities for Java EE, relacionadas con la agrupación de hebras, que 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 el WebSphere Application Server tradicional, cada gestor de trabajo se puede configurar con dos agrupaciones de hebras. 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 utilizar Concurrency Utilities for Java EE con agrupaciones de hebras separadas en Liberty, se pueden adoptar varios enfoques para conseguir un comportamiento similar a las opciones de configuración que están disponibles en el WebSphere Application Server tradicional.
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.
Ejemplo de sustitución para un máximo de hebras de trabajo y una configuración de cola de trabajos
int minThreads = 1;
int maxThreads = 2;
int workRequestQueueSize = 3;
RejectedExecutionHandler workRequestQueueFullAction =
new ThreadPoolExecutor.AbortPolicy();
ManagedThreadFactory threadFactory =
(ManagedThreadFactory) new InitialContext().lookup(
"java:comp/DefaultManagedThreadFactory");
ExecutorService executor = new ThreadPoolExecutor(
minThreads, // similar, but not exact match for coreSize
maxThreads, keepAliveTime, keepAliveTimeUnit,
new ArrayBlockingQueue<Runnable>(workRequestQueueSize),
threadFactory,
workRequestQueueFullAction);
Callable<Integer> task = new MyTask();
Future<Integer> future = executor.submit(task);
int result = future.get();
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();
Aplicación de un tiempo de espera de trabajo
El WebSphere Application Server tradicional le permite configurar un tiempo de espera de trabajo que se aplica a tareas que se han enviado para ejecutarse lo antes posible (métodos submit/execute/invoke). Si una tarea se está ejecutando durante más tiempo que el tiempo de espera del trabajo asignado, se realiza un intento para cancelar la tarea interrumpiéndola. Sin embargo, Liberty no tiene el tiempo de espera del trabajo como una opción de configuración, pero se puede implementar un comportamiento similar enviando la tarea con un escucha de tarea gestionada, que, como respuesta a la notificación taskStarting, planifique una tarea para cancelar el Future de la tarea. De forma alternativa, al utilizar un ejecutor de agrupación de hebras como en el ejemplo anterior, donde el escucha de la tarea gestionada no está disponible, es posible alterar temporalmente el método beforeExecute del ejecutor de la agrupación de hebras para planificar una tarea para interrumpir la hebra 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) {}
}