工作管理器提供针对 Java™ Platform Enterprise Edition (Java EE)
应用程序的线程处理。
使用管理控制台,管理员可配置任何数量的工作管理器。管理员指定工作管理器的属性,包括提交到工作管理器的任务的 Java EE 上下文继承策略。管理员将每个工作管理器绑定到 Java 命名和目录接口 (JNDI) 中的唯一位置。您可在下列某个接口中使用工作管理器对象:
- 受管执行程序
- javax.enterprise.concurrent.ManagedExecutorService
- javax.enterprise.concurrent.ManagedScheduledExecutorService
- java.util.concurrent.ExecutorService
- java.util.concurrent.ScheduledExecutorService
- 线程工厂
- javax.enterprise.concurrent.ManagedThreadFactory
- java.util.concurrent.ThreadFactory
- 线程上下文服务
- javax.enterprise.concurrent.ContextService
- 异步 bean
- com.ibm.websphere.asynchbeans.WorkManager
- CommonJ 工作管理器
在 JNDI 查找时间(基于您在资源环境引用中指定的值)内解析所选类型的接口。
工作管理器提供 Java EE 应用程序的编程模型。有关更多信息,请参阅“编程模型”部分。
避免故障: javax.resource.spi.work.WorkManager 类是一个 Java 接口,供 Java EE 连接器体系结构 (JCA) 资源适配器使用。它不是 Java EE 应用程序使用的工作管理器的实际实现。
gotcha
编写使用 Java EE 并行实用程序或异步 bean 的 Web 组件或 Enterprise JavaBeans (EJB)
组件时,开发者必须在需要访问受管执行程序、线程工厂、上下文服务或工作管理器的每个组件中添加资源环境引用。有关资源引用的更多信息,请参阅“引用”主题。该组件按查找数据源、企业 bean 或连接工厂的方式查找在组件中使用逻辑名(即 java: comp namespace)的受管执行程序、线程工厂、上下文服务或工作管理器。
部署应用程序时,部署者将物理工作管理器绑定至逻辑资源环境引用(受管执行程序、线程工厂、上下文服务或工作管理器)。
例如,如果开发者需要三个线程池,以对铜、银和金级别之间的工作进行分区,开发者编写此组件,以根据客户机应用程序概要文件中的属性选取逻辑池。部署者拥有确定如何为三个线程池映射此请求灵活性。部署者可确定在小型系统上使用单个线程池。在此情况下,部署者将所有三个资源引用绑定到同一工作管理器实例(即,同一 JNDI 名称)。大型系统可支持三个线程池,所以部署者将每个资源引用绑定至不同工作管理器。可在同一服务器上安装的多个 Java EE 应用程序之间共享工作管理器。
应用程序开发者可根据需要使用任意数目的逻辑资源环境引用。部署者选择是将一个物理工作管理器还是若干工作管理器映射至应用程序中定义的逻辑受管执行程序、线程工厂、上下文服务或工作管理器。
需要共享异步作用域对象的所有 Java EE 组件必须使用相同的工作管理器。这些范围对象具有与单个工作管理器的亲缘关系。使用异步范围的应用程序必须验证使用范围对象的所有组件是否也使用相同的工作管理器。
当定义多个工作管理器时,仅当 Java 虚拟机 (JVM) 中的应用程序查找工作管理器时,才在此 JVM 中创建底层线程池。例如,如果已定义 10
个线程池(工作管理器),那么应用程序查找这些池前,不会创建任何池。
要点: 工作管理器不支持将工作提交至远程 JVM。
CommonJ 工作管理器
CommonJ 工作管理器包含异步 bean 工作管理器方法的子集。尽管 CommonJ 工作管理器在 Java EE 1.4 环境中可以使用,但是此接口不会对每个 JNDI 命名查询都返回新实例,这是因为此规范未包含在 Java EE 规范中。
不支持远程执行工作这项 CommonJ 工作规范可选功能。即使工作单元实现了 java.io.Serializable 接口,工作单元也无法远程运行。
如何查找受管执行程序
应用程序可按如下所示查找受管执行程序。此处,组件包含名为
concurrent/myExecutor 的资源环境引用,部署组件时它被绑定至物理工作管理器:
InitialContext ic = new InitialContext();
ManagedExecutorService executor = (ManagedExecutorService) ic.lookup("java:comp/env/concurrent/myExecutor");
继承 Java EE 上下文
提交至受管执行程序和工作管理器的任务可从提交线程继承以下 Java EE 上下文。上下文代理可从调用上下文服务以创建上下文代理的线程继承这些类型的上下文。受管线程工厂线程可从查找或插入受管线程工厂的线程继承这些类型的上下文。
- 国际化上下文
- 当选择此选项并启用国际化服务时,并且调度线程中存在的国际化上下文在目标线程上可用。
- 工作区
- 当选择此选项时,调度线程上存在的每个工作区分区的工作区上下文在目标线程上可用。
- 应用程序概要文件(建议不要使用)
- 大多数应用程序不支持应用程序概要文件上下文,且应用程序概要文件上下文在其中不可用。对于 Java EE 1.3 应用程序,选择此选项并启用应用程序概要文件服务,并选择应用程序概要文件服务属性 5.x 兼容性方式。与调度线程关联的应用程序概要文件任务在 Java EE 1.3 应用程序的目标线程上可用。对于 Java EE 1.4 或更高版本的应用程序,应用程序概要文件任务是其关联的工作单元的属性,而不是线程。此选项对于 Java EE 1.4 或更高版本的应用程序中任务的行为无影响。Java EE 1.4
应用程序中运行的所安排工作不会接收安排线程的概要分析任务。
- 安全性
- 该任务可以匿名方式运行,或作为在创建并提交它的线程上认证的客户机运行。因为该任务只能执行调用者可执行的任务,所以此行为是有用的。此操作比 RUN_AS 机制更有用,例如,它可以防止此类型的行为发生。当您选择安全性选项时,调度线程上存在的 JAAS 主体集在目标线程上可用。如果未选择,那么此线程匿名运行。
- 组件元数据
- 仅当任务是简单 Java 对象时,才与组件元数据有关。如果任务是 Java EE 组件(如企业 Bean),那么组件元数据是活动的。
可继承的上下文依赖于创建并提交任务的应用程序所使用的工作管理器。使用管理控制台,管理员通过选择工作管理器变得可用的服务,定义工作管理器的粘性上下文策略。
并行性示例
表 1. 查找受管执行程序或工作管理器受管执行者 |
异步 bean |
CommonJ |
InitialContext ctx = new InitialContext();
ManagedExecutorService executor =
(ManagedExecutorService)
ctx.lookup("java:comp/env/wm/myWorkMgr");
|
InitialContext ctx = new InitialContext();
com.ibm.websphere.asynchbeans.WorkManager wm =
(com.ibm.websphere.asynchbeans.WorkManager)
ctx.lookup(“java:comp/env/wm/MyWorkMgr”);
|
InitialContext ctx = new InitialContext();
commonj.work.WorkManager wm =
(commonj.work.WorkManager)
ctx.lookup(“java:comp/env/wm/MyWorkMgr”);
|
表 2. 创建任务受管执行者 |
异步 bean |
CommonJ |
public class MyWork implements Callable<Integer> {
public Integer call() {
System.out.println(“Running.....”);
return 1;
}
}
|
public class MyWork implements
com.ibm.websphere.asynchbeans.Work {
public void release() {
......
}
public void run() {
System.out.println(“Running.....”);
}
|
public class MyWork implements
commonj.work.Work{
public boolean isDaemon() {
return false;
}
public void release () {
.....
}
public void run () {
System.out.println(“Running.....”);
}
|
表 3. 提交任务受管执行者 |
异步 bean |
CommonJ |
MyWork work1 = new MyWork();
MyWork work2 = new MyWork();
// case 1: block until all items are done
Collection<MyWork> tasks =
Arrays.asList(work1, work2);
List<Future<Integer>> futures =
executor.invokeAll(tasks);
for (Future<Integer> future : futures)
System.out.println("work data=" + future.get());
//case 2: wait up to 1000 milliseconds for any of the items to complete.
Integer result = executor.invokeAny(
tasks, 1, TimeUnit.SECONDS);
System.out.println("work data=" + result);
|
MyWork work1 = new MyWork();
MyWork work2 = new MyWork();
WorkItem item1;
WorkItem item2;
Item1=wm.startWork(work1);
Item2=wm.startWork(work2);
// case 1: block until all items are done
ArrayList col1 = new ArrayList();
Col1.add(item1);
Col1.add(item2);
wm.join(col1, WorkManager.JOIN_AND, WorkManager.INDEFINITE);
// when the works are done
System.out.println(“work1 data=”+work1.getData());
System.out.println(“work2 data=”+work2.getData());
// you should complete case 1 before case 2
// case 2: wait up to 1000 milliseconds
for any of the items to complete.
Boolean ret = wm.join(col1, WorkManager.JOIN_OR, 1000);
|
MyWork work1 = new MyWork();
MyWork work2 = new MyWork();
WorkItem item1;
WorkItem item2;
Item1=wm.schedule(work1 );
Item2=wm.schedule(work2);
// case 1: block until all items are done
Collection col1 = new ArrayList();
col1.add(item1);
col1.add(item2);
wm.waitForAll(col1, WorkManager.INDEFINITE);
// when the works are done
System.out.println(“work1 data=”+work1.getData());
System.out.println(“work2 data=”+work2.getData());
// you should complete case 1 before case 2
// case 2: wait up to 1000 milliseconds for any of the items to complete.
Collection finished = wm.waitForAny(col1,1000);
// check the workItems status
if (finished != null) {
Iterator I = finished.iterator();
if (i.hasNext()) {
WorkItem wi = (WorkItem) i.next();
if (wi.equals(item1)) {
System.out.println(“work1 =
“+ work1.getData());
} else if (wi.equals(item2)) {
System.out.println(“work1 =
“+ work1.getData());
}
}
}
|
表 4. 创建受管已调度执行者、警报管理器或计时器管理器受管已调度执行者 |
异步 Bean |
CommonJ |
InitialContext ctx = new InitialContext();
ManagedScheduledExecutorService executor =
(ManagedScheduledExecutorService)
ctx.lookup("java:comp/env/wm/MyWorkMgr");
|
InitialContext ctx = new InitialContext();
com.ibm.websphere.asynchbeans.WorkManager wm =
(com.ibm.websphere.asynchbeans.WorkManager)
ctx.lookup(“java:comp/env/wm/MyWorkMgr”);
AsynchScope ascope;
Try {
Ascope = wm.createAsynchScope(“ABScope”);
} Catch (DuplicateKeyException ex)
{
Ascope = wm.findAsynchScope(“ABScope”);
ex.printStackTrace();
}
// get an AlarmManager
AlarmManager aMgr= ascope.getAlarmManager();
|
InitialContext ctx = new InitialContext();
Commonj.timers.TimerManager tm =
(commonj.timers.TimerManager)
ctx.lookup(“java:comp/env/tm/MyTimerManager”);
|
表 5. 调度任务、警报或计时器。受管已调度执行者 |
异步 bean |
CommonJ |
// create task
Runnable task = new StockQuoteTask(
“qqq”, “johndoe@example.com”);
ScheduledFuture<?> future =
executor.schedule(task, 1, TimeUnit.MINUTES);
// Fixed-delay: schedule task to run
// 1 minute from now and repeat every
// hour thereafter.
ScheduledFuture<?> future =
executor.scheduleWithFixedDelay(
task, 1, 60, TimeUnit.MINUTES);
// Fixed-rate: schedule timer to expire
// 1 minute from now and repeat every
// hour thereafter
ScheduledFuture<?> future =
executor.scheduleAtFixedRate(
task, 1, 60, TimeUnit.MINUTES);
|
// create alarm
ABAlarmListener listener = new ABAlarmListener();
Alarm am =
aMgr.create(listener, “SomeContext”, 1000*60);
|
// create timer
TimerListener listener =
new StockQuoteTimerListener(“qqq”,
“johndoe@example.com”);
Timer timer = tm.schedule(listener, 1000*60);
// Fixed-delay: schedule timer to expire in
// 60 seconds from now and repeat every
// hour thereafter.
Timer timer = tm.schedule(listener, 1000*60, 1000*30);
// Fixed-rate: schedule timer to expire in
// 60 seconds from now and repeat every
// hour thereafter
Timer timer = tm.scheduleAtFixedRate(listener, 1000*60, 1000*30);
|