將使用並行和非同步程式設計模型的應用程式移轉至 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 傳統版所提供之配置選項的行為。
![[17.0.0.4 以及更新版本]](../ng_v17004plus.gif)
使用並行原則配置
使用 concurrencyPolicy 元素,將 WebSphere Application Server 傳統版中的某些行為,抄寫到 Liberty 中。下表列出 concurrencyPolicy 元素的可用配置選項,以及這個元素與 WebSphere Application Server 傳統版的比較。concurrencyPolicy 配置不會套用至排程作業。
Liberty 受管理執行程式 concurrencyPolicy | WebSphere Application Server 傳統版 工作管理員和受管理執行程式 |
---|---|
max | 執行緒數目上限 |
maxQueueSize | 工作要求佇列大小 |
maxWaitForEnqueue | 工作要求佇列滿載時的動作 = WAIT |
runIfQueueFull = false | 工作要求佇列滿載時的動作 = FAIL |
startTimeout | 啟動逾時值 |
longRunningPolicyRef + longrunning hint | 常駐程式工作 |
expedite 元素等於 Liberty 廣域執行緒儲存區中要加快處理的執行緒數目目標下限,而不是等於執行緒數目固定下限。
建構 Java SE 執行程式,以伴隨受管理執行緒 Factory 執行
Java SE 的 java.util.concurrent 套件提供數種方式,將執行緒儲存區建構成執行程式和排定的執行程式,以伴隨特定的執行緒 Factory 執行。您可以提供受管理執行緒 Factory,來取代未受管理的執行緒 Factory,以產生一個在受管理執行緒上執行作業的執行緒儲存區。不同於受管理執行程式和受管理排定執行程式,被這些執行程式排入儲存區的受管理執行緒在執行時,會使用查閱受管理執行緒 Factory 期間的執行緒環境定義,而不是使用提交或排定作業期間的執行緒環境定義。在執行緒週期內,受管理執行緒中會保留執行緒環境定義,如此可減輕執行緒環境定義額外的切換負擔。
![[17.0.0.4 以及更新版本]](../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 以及更新版本]](../ng_v17004plus.gif)
套用啟動逾時值
<managedExecutorService jndiName="concurrent/execSvc">
<concurrencyPolicy startTimeout="1m"/>
</managedExecutorService>
套用工作逾時值
使用 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) {}
}
![[17.0.0.4 以及更新版本]](../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);