Anwendungen, die Parallelität und asynchrone Programmiermodelle verwenden, auf Liberty migrieren

Sie können Anwendungen, die Concurrency Utilities for Java™ EE, asynchrone Beans und CommonJ-Zeitgeber- und Arbeitsmanager verwenden, von WebSphere Application Server Traditional auf WebSphere Application Server Liberty migrieren.

Asynchronous Beans, CommonJ-Zeitgeber und Arbeitsmanager sind in Liberty nicht verfügbar. Bei einer Migration auf Liberty müssen Anwendungen auf das Programmiermodell von Concurrency Utilities for Java EE umgestellt werden. Weitere Informationen finden Sie unter Beispiel-API-Tasks, die Concurrency Utilities for Java EE implementieren.

Unterschiede bei der Konfiguration und beim Threading

WebSphere Application Server Traditional stellt eine Reihe von Konfigurationsoptionen für Concurrency Utilities for Java EE bereit, die sich auf das Thread-Pooling beziehen, das anders konfiguriert oder nicht in Liberty verfügbar ist. Liberty verwendet einen einzigen allgemeinen Thread-Pool für alle Steuerprogramme für verwaltete und verwaltete geplante Tasks, die auch von Liberty-Komponenten genutzt werden. Auf diese Weise kann Liberty das Thread-Management optimieren. In WebSphere Application Server Traditional kann jeder Arbeitsmanager mit zwei Thread-Pools konfiguriert werden. Ein Thread-Pool ist für Tasks bestimmt, die zur möglichst schnellen Ausführung übergeben werden (Methoden submit/execute/invoke des Steuerprogramms für verwaltete Tasks), und hat eine konfigurierbare Arbeitsanforderungswarteschlange sowie Aktionen, die beim Überschreiten der Warteschlangenkapazität ausgeführt werden sollen. Der andere Thread-Pool ist für geplante Tasks (Methode "schedule" des Steuerprogramms für verwaltete geplante Tasks) bestimmt.

Wenn Sie vorhaben, Concurrency Utilities for Java EE mit separaten Thread-Pools in Liberty zu verwenden, stehen verschiedene Lösungen zur Verfügung, um ein Verhalten zu erzielen, das den in WebSphere Application Server Traditional verfügbaren Konfigurationsoptionen gleicht.

[17.0.0.4 und höher]

Richtlinienkonfiguration für gemeinsamen Zugriff verwenden

Verwenden Sie das Element concurrencyPolicy, um einen Teil des Verhaltens von WebSphere Application Server Traditional in Liberty nachzubilden. In der folgenden Tabelle sind die verfügbaren Konfigurationsoptionen für das Element concurrencyPolicy zusammen mit Hinweisen, wie sich dieses Element im Vergleich zu WebSphere Application Server Traditional verhält, enthalten. Die concurrencyPolicy-Konfiguration gilt nicht für geplante Tasks.

Tabelle 1.
Von Liberty verwaltete Steuerprogramme des Typs concurrencyPolicy Arbeitsmanager und verwaltete Steuerprogramme von WebSphere Application Server Traditional
   
max Maximale Anzahl der Threads
maxQueueSize Größe der Verarbeitungsanforderungswarteschlange
maxWaitForEnqueue Aktion, wenn Verarbeitungsanforderungswarteschlange voll ist: WAIT
runIfQueueFull = false Aktion, wenn Verarbeitungsanforderungswarteschlange voll ist: FAIL
startTimeout Startzeitlimit
longRunningPolicyRef + longrunning hint Dämonprozess

Das expedite-Element entspricht einer Mindestanzahl von Zielthreads, die im globalen Liberty-Thread-Pool ausgeführt werden, anstelle einer festen Mindestanzahl von Threads.

Java SE-Steuerprogramm mit einer Factory für verwaltete Threads (Managed-Thread-Factory) erstellen

Das Paket java.util.concurrent von Java SE bietet mehrere Möglichkeiten für die Erstellung von Thread-Pools als Steuerprogramme und Steuerprogramme für geplante Threads mit einer bestimmten Thread-Factory. Anstelle einer Factory für verwaltete Threads kann eine Factory für nicht verwaltete Threads bereitgestellt werden, woraufhin ein Thread-Pool generiert wird, in dem Tasks in verwalteten Threads ausgeführt werden. Anders als das Steuerprogramm für verwaltete Tasks und die Steuerprogramme für verwaltete geplante Tasks werden die von diesen Steuerprogrammen in den Pool gestellten verwalteten Threads mit dem Threadkontext ausgeführt, der bei der Suche der Factory für verwaltete Threads gültig war, und nicht mit dem Threadkontext, der bei der Übergabe oder Planung der Task gültig war. Der Thread behält diesen Threadkontext für seine gesamte Lebensdauer, was den Aufwand für den Wechsel des Threadkontextes reduziert.

[17.0.0.4 und höher]

Beispiel für die Ersetzung der maximalen Arbeitsthreadanzahl und die Konfiguration der Arbeitswarteschlange

<managedExecutorService jndiName="concurrent/execSvc">
    <concurrencyPolicy max="2" maxQueueSize="3" runIfQueueFull="false" maxWaitForEnqueue="0"/>
</managedExecutorService>

Beispiel für die Ersetzung der maximalen Alarmthreadanzahl

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 und höher]

Startzeitlimit anwenden

<managedExecutorService jndiName="concurrent/execSvc">
    <concurrencyPolicy startTimeout="1m"/>
</managedExecutorService>

Arbeitszeitlimit anwenden

Verwenden Sie WebSphere Application Server Traditional, um ein Arbeitszeitlimit zu konfigurieren, das für Tasks gilt, die zur möglichst schnellen Ausführung übergeben werden (Methoden submit/execute/invoke). Wenn das zulässige Arbeitszeitlimit bei der Ausführung einer Task überschritten wird, versucht das Programm, die Task durch Unterbrechung abzubrechen. In Liberty wird das Arbeitszeitlimit nicht als Konfigurationsoption angeboten, aber ein ähnliches Verhalten kann durch Übergabe der Task mit einem Listener für verwaltete Tasks übergeben werden. Als Antwort auf die taskStarting-Benachrichtigung plant der Listener für verwaltete Tasks eine Task zum Abbrechen der Methode Future. Wenn Sie ein Thread-Pool-Steuerprogramm verwenden, wenn ein Listener für verwaltete Tasks nicht verfügbar ist, können Sie alternativ die Methode beforeExecute des Steuerprogramms des Thread-Pools überschreiben, um eine Tasks für die Unterbrechung des Ausführungsthreads zu planen.

Beispiel für die Ersetzung des Arbeitszeitlimits

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 erfolgreich...
} catch (CancellationException x) {
    // Task abgebrochen, möglicherweise wegen einer Zeitlimitüberschreitung
}

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 und höher]

Beispiel für Dämonprozesse

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);

Symbol das den Typ des Artikels anzeigt. Referenzartikel

Dateiname: rwlp_mig_workmgr.html