将使用并行和异步编程模型的应用程序迁移到 Liberty
您可以将使用 Concurrency Utilities for Java™ EE、异步 Bean 和 CommonJ Timer and Work Manager 的实用程序从 WebSphere® Application Server 传统版迁移到 WebSphere Application Server Liberty。
异步 Bean 和 CommonJ Timer and Work Manager 在 Liberty 中不可用。迁移到 Liberty 时,应用程序必须切换为 Concurrency Utilities for Java EE 编程模型。有关更多信息,请参阅实现 Concurrency Utilities for Java EE 的 API 任务示例。
配置和线程技术方面的差别
WebSphere Application Server 传统版为 Concurrency Utilities for Java EE 提供了许多与线程池相关的配置选项,这些选项在 Liberty 中不可用。Liberty 具有单个跨所有受管执行程序和受管调度执行程序(这些执行程序也由 Liberty 组件共享)的公共线程池。这允许 Liberty 优化线程管理。在 WebSphere Application Server 传统版中,可以为每个工作管理器配置两个线程池。一个线程池用于提交以尽快运行的任务(受管执行程序的提交/执行/调用方法),并且具有可配置的工作请求队列以及在超过队列容量时要执行的操作。另一个线程池用于调度的任务(受管调度执行程序的调度方法)。
如果您打算在 Liberty 中将 Concurrency Utilities for Java EE 与不同的线程池配合使用,那么可采用各种方法来实现类似于 WebSphere Application Server 传统版中可用的配置选项的行为。
基于受管线程工厂构造 Java SE 执行程序
Java SE 的 java.util.concurrent 包提供了多种方法,用于基于特定线程工厂构造线程池作为执行程序和调度执行程序。可以提供受管线程工厂来取代非受管线程工厂,这将生成一个在受管线程中运行任务的线程池。与受管执行程序和受管调度执行程序不同,由这些执行程序合用的受管线程从查找受管线程工厂时起(而不是从提交或调度任务时起)使用线程上下文运行。线程上下文在线程生存期内也保留在受管线程中,这可减少线程上下文切换开销。
最大工作线程数和工作队列配置的替代项示例
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();
最大警报线程数的替代项示例
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();
应用工作超时
WebSphere Application Server 传统版允许您配置适用于提交以尽快运行的任务(提交/执行/调用方法)的工作超时。如果任务运行时间超过分配的工作超时,将会尝试通过中断该任务来将其取消。然而,Liberty 没有将工作超时作为配置选项,但可以实现类似的行为,方法如下:使用受管任务侦听器提交任务,该侦听器为了响应 taskStarting 通知,将调度任务以取消任务的 Future。另外,使用线程池执行程序时(如以上示例),在受管任务侦听器不可用的情况下,可能会覆盖线程池执行程序的 beforeExecute 方法以调度任务来中断执行线程。
工作超时的替代项示例
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);
// task successful...
} catch (CancellationException x) {
// task was canceled, possibly due to timeout
}
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) {}
}