並行性プログラミング・モデルおよび非同期のプログラミング・モデルを使用するアプリケーションの Liberty へのマイグレーション
Concurrency Utilities for Java™ EE、非同期 Bean 、CommonJ Timer and Work Manager を使用するアプリケーションを WebSphere® Application Server traditional から 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 traditional には、スレッド・プールに関連した、Concurrency Utilities for Java EE 用のいくつかの構成オプションがありますが、これらのオプションは、Liberty では構成方法が異なるか、使用可能ではありません。Liberty には、すべての管理対象 executor および管理対象スケジュール executor 全体にわたって共通する、単一スレッド・プールがあります。これらの executor は Liberty コンポーネントでも共有されます。これにより、Liberty でスレッド管理を最適化することができます。WebSphere Application Server traditional では、2 つのスレッド・プールを使用して各作業マネージャーを構成することができます。一方のスレッド・プールは、できるだけ早く実行するように実行依頼されているタスク (管理対象 executor の submit/execute/invoke メソッド) のためのもので、構成可能な作業要求キューと、キュー容量が超過した場合に取るアクションが指定されています。もう一方のスレッド・プールは、スケジュール済みタスク (管理対象スケジュール executor の schedule メソッド) のためのものです。
Liberty で別のスレッド・プールを指定して Concurrency Utilities for Java EE を使用する予定の場合は、さまざまな方法で、WebSphere Application Server traditional で使用可能な構成オプションと同様の動作を実行することができます。
![[17.0.0.4 and later]](../ng_v17004plus.gif)
並行性ポリシー構成の使用
concurrencyPolicy エレメントを使用して、WebSphere Application Server traditional の動作の一部を Liberty で複製します。次の表に、concurrencyPolicy エレメントに使用できる構成オプションをリストし、 WebSphere Application Server traditional とこのエレメントの比較を示します。concurrencyPolicy 構成は、スケジュールされたタスクには適用されません。
Liberty 管理対象 executor concurrencyPolicy | WebSphere Application Server traditional 作業マネージャーおよび管理対象 executor |
---|---|
max | 最大スレッド数 |
maxQueueSize | 作業要求キュー・サイズ |
maxWaitForEnqueue | 作業要求キュー・フル・アクション = WAIT |
runIfQueueFull = false | 作業要求キュー・フル・アクション = FAIL |
startTimeout | 開始タイムアウト |
longRunningPolicyRef + longrunning hint | デーモン作業 |
expedite エレメントと等しいのは、固定の最小スレッド数ではなく、Liberty グローバル・スレッド・プールで処理されるターゲット最小スレッド数です。
管理対象スレッド・ファクトリーの Java SE executor の構成
Java SE の java.util.concurrent パッケージには、スレッド・プールを特定のスレッド・ファクトリーの executor およびスケジュール executor として構成するための方法がいくつか用意されています。管理対象スレッド・ファクトリーは、管理対象外スレッド・ファクトリーの代わりに指定して、管理対象スレッドに対するタスクを実行するスレッド・プールを作成することができます。これらの executor によってプールされた管理対象スレッドは、管理対象 executor や管理対象のスケジュールされた executor とは異なり、タスクを実行依頼またはスケジュールしたときからではなく、管理対象スレッド・ファクトリーを検索したときからスレッド・コンテキストで実行されます。また、スレッド・コンテキストは、スレッドの存続期間中は管理対象スレッド上に残ります。これにより、スレッド・コンテキストの切り替えによるオーバーヘッドが削減されます。
![[17.0.0.4 and later]](../ng_v17004plus.gif)
最大作業スレッドの置き換えと作業キュー構成の例
<managedExecutorService jndiName="concurrent/execSvc">
<concurrencyPolicy max="2" maxQueueSize="3" runIfQueueFull="false" maxWaitForEnqueue="0"/>
</managedExecutorService>
最大アラーム・スレッドの置き換えの例
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)
開始タイムアウトの適用
<managedExecutorService jndiName="concurrent/execSvc">
<concurrencyPolicy startTimeout="1m"/>
</managedExecutorService>
作業タイムアウトの適用
WebSphere Application Server traditional を使用して、できるだけ早く実行するように実行依頼するタスク (submit/execute/invoke メソッド) に適用される作業タイムアウトを構成します。割り当てられた作業タイムアウトよりもタスクの実行時間が長い場合、本プログラムはそのタスクを中断することによってタスクを取り消そうとします。Liberty には構成オプションとしての作業タイムアウトはありませんが、管理対象タスク・リスナーを使用してタスクを実行依頼することによって、同様の動作を実装できます。taskStarting 通知への応答で、管理対象タスク・リスナーは、Future メソッドを取り消すためのタスクをスケジュールします。管理対象タスク・リスナーが使用できない場合は、代わりにスレッド・プール executor を使用すると、スレッド・プール executor の 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) {}
}
![[17.0.0.4 and later]](../ng_v17004plus.gif)
デーモン作業の例
Configuration:
<concurrencyPolicy id="longRunning" max="2"/>
<managedExecutorService jndiName="concurrent/execSvc" longRunningPolicyRef="longRunning" />
Application code:
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);