配置受管执行程序
您可以配置 ManagedExecutorService 实例,以使用所指定线程上下文来运行异步任务。Java™ EE 应用程序最好避免直接管理它们自己的线程;因此,ManagedExecutorService 扩展 JSE ExecutorService,以提供一种在应用程序服务器环境中启动异步任务的方法。另外,还可配置 ManagedExecutorService 以将 Java EE 应用程序的各种相关线程上下文传播至该异步任务的线程。
关于此任务
<featureManager>
<feature>concurrent-1.0</feature>
</featureManager>
将上下文传播至 ManagedExecutorService 所运行任务的线程是由上下文服务管理。服务器会创建上下文服务的缺省实例 (DefaultContextService),该实例配置为至少传播 classloaderContext、jeeMetadataContext 和 securityContext。如果创建 ManagedExecutorService 时没有引用特定的上下文服务实例,也没有直接在其中配置上下文服务实例,那么将使用这个缺省上下文服务实例。有关上下文服务实例的更多信息,请参阅“配置线程上下文服务实例”主题。
缺省的受管执行程序实例 (DefaultManagedExecutorService) 以 java:comp/DefaultManagedExecutorService 形式提供,并使用缺省的上下文服务实例来捕获和传播线程上下文。
并行策略用于配置要应用于受管执行程序的并行相关行为及约束,例如,最大并行度和最大队列大小。缺省情况下,受管执行程序使用
concurrencyPolicy 配置元素的缺省实例
defaultConcurrencyPolicy,该实例具有无限制的约束。如果您配置受管执行程序,但没有以嵌套元素形式引用或直接配置特定的
concurrencyPolicy 元素,那么将使用这个缺省并行策略。如果多个受管执行程序或其他配置元素引用同一个 concurrencyPolicy 元素,那么该策略中的约束将应用于所有这些受管执行程序实例和其他已配置的资源。另外,还可以为受管执行程序配置一个用于长时间运行的任务的并行策略,该策略将应用于 LONGRUNNING_HINT 执行属性设置为 true 的任务。在
concurrencyPolicy 元素以及长时间运行 concurrencyPolicy
元素中指定的配置将应用于提交为尽快运行的任务。此配置不适用于调度的任务。
过程
server.xml 文件中的示例配置:
示例
受管执行程序服务实例可通过 @Resource 插入到应用程序组件中,或通过资源环境引用 (resource-env-ref) 进行查找。无论如何获取实例,都可按 javax.enterprise.concurrent.ManagedExecutorService 或其 java.util.concurrent.ExecutorSerivce 超类的形式互换使用。
- 查找缺省受管执行程序的示例:
ManagedExecutorService executor = (ManagedExecutorService) new InitialContext().lookup( "java:comp/DefaultManagedExecutorService"); executor.submit(doSomethingInParallel);
- 使用 @Resource 以注入为 java.util.concurrent.ExecutorService 的示例:
@Resource(lookup="concurrent/execSvc1") ExecutorService execSvc1; ... // submit task to run Future<Integer> future1 = execSvc1.submit(new Callable<Integer>() { public Integer call() throws Exception { // java:comp lookup is possible because <jeeMetadataContext> is configured DataSource ds = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/ds1"); ... make updates to the database return updateCount; } }); Future<Integer> future2 = execSvc1.submit(anotherTaskThatUpdatesADatabase); numUpdatesCompleted = future1.get() + future2.get();
- 使用 @Resource 以注入为 javax.enterprise.concurrent.ManagedExecutorService 的示例:
@Resource(lookup="concurrent/execSvc1") ManagedExecutorService execSvc1; ... // submit task to run Future<Integer> future1 = execSvc1.submit(new Callable<Integer>() { public Integer call() throws Exception { // java:comp lookup is possible because <jeeMetadataContext> is configured DataSource ds = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/ds1"); ... make updates to the database return updateCount; } }); Future<Integer> future2 = execSvc1.submit(anotherTaskThatUpdatesADatabase); numUpdatesCompleted = future1.get() + future2.get();
- web.xml 文件中 java.util.concurrent.ExecutorService 的
<resource-env-ref> 示例:
<resource-env-ref> <resource-env-ref-name>concurrent/execSvc2</resource-env-ref-name> <resource-env-ref-type>java.util.concurrent.ExecutorService</resource-env-ref-type> </resource-env-ref>
- 使用资源环境引用的查找示例:
ExecutorService execSvc2 = (ExecutorService) new InitialContext().lookup("java:comp/env/concurrent/execSvc2"); futures = execSvc2.invokeAll(Arrays.asList(task1, task2, task3));
- web.xml 文件中 javax.enterprise.concurrent.ManagedExecutorService 的 <resource-env-ref> 示例:
<resource-env-ref> <resource-env-ref-name>concurrent/execSvc2</resource-env-ref-name> <resource-env-ref-type>javax.enterprise.concurrent.ManagedExecutorService</resource-env-ref-type> </resource-env-ref>
- 使用资源环境引用并强制转换为 ManagedExecutorService 的查找示例:
ManagedExecutorService execSvc2 = (ManagedExecutorService) new InitialContext().lookup("java:comp/env/concurrent/execSvc2"); futures = execSvc2.invokeAll(Arrays.asList(task1, task2, task3));