Exemples de migration vers les accès concurrents EE à partir d'Asynchronous beans et de CommonJ

Vous pouvez faire migrer des applications qui utilisent des API Asynchronous beans et CommonJ Timer and Work Manager afin d'utiliser Concurrency Utilities for Java™ EE.

Les utilitaires Concurrency Utilities for Java EE fournissent une approche standard de l'exécution d'opérations simultanées sur un serveur d'applications. Ils remplacent les modèles de programmation pour Asynchronous beans et CommonJ Timer and Work Manager. Les exemples de code de cette page montrent comment migrer des applications existantes afin qu'elles utilisent Concurrency Utilities for Java EE.

Fonction obsolète Fonction obsolète: Les API Asynchronous beans et CommonJ sont obsolètes.depfeat

Ressources utilisées dans les exemples de code

Les exemples de code de cette page supposent que l'application a injecté ou a consulté les ressources suivantes :

@Resource(lookup = "wm/default")
private com.ibm.websphere.asynchbeans.WorkManager abWorkManager;

@Resource(lookup = "wm/default")
private commonj.work.WorkManager cjWorkManager;

@Resource
private ContextService contextService;

@Resource(name = "java:app/env/jdbc/dsRef")
private DataSource dataSource;

@Resource
private ManagedScheduledExecutorService executor;

@Resource
private ManagedThreadFactory threadFactory;

@Resource(name = "java:comp/env/tm/default", lookup = "tm/default", shareable = false)
private TimerManager timerManager;

@Resource
private UserTransaction tran;

Implémentation de tâches de base

Cette section fournit des exemples d'implémentation de tâche simple utilisée par les autres exemples tout au long du présent document. Asynchronous beans requiert une interface distincte, AlarmListener, pour les tâches planifiées pour une exécution future. CommonJ requiert une interface distincte, TimerListener, pour les tâches planifiées pour une exécution future. Les tâches Concurrency Utilities for Java EE peuvent être Runnable (exécutables) ou Callable (appelables), et toute interface peut être utilisée, que la tâche soit soumise pour exécution immédiate ou planifiée pour une exécution future. Dans certains cas, il est possible de soumettre Asynchronous beans ou CommonJ Work en tant que Runnable à un programme d'exécution géré sans avoir effectué de modification. La méthode release de Work est remplacée par la possibilité, pour les programmes d'exécution gérés, d'annuler ou d'interrompre les unités d'exécution en cours. La méthode isDaemon de Work est remplacée par la propriété d'exécution LONGRUNNING_HINT.

Exemple de tâche Work pour Asynchronous beans et CommonJ qui recherche le nombre premier suivant :

public class PrimeFinderWork implements
    com.ibm.websphere.asynchbeans.Work, commonj.work.Work {
    private long num;
    private volatile boolean released;
    private long result;

    public PrimeFinderWork(long startingValue) {
        num = startingValue;
    }

    public boolean isDaemon() {
        return false;
    }
    public void release() {
        released = true;
    }

    public void run() {
        while (!isPrime(num))
            if (released || Thread.currentThread().isInterrupted())
                throw new RuntimeException(new InterruptedException());
            else
                num++;
        result = num++;
    }

    public long getPrimeNumber() {
        if (result > 0)
            return result;
        else
            throw new IllegalStateException();
    }
}

Exemple de tâche AlarmListener pour Asynchronous beans qui recherche le nombre premier suivant :

public class PrimeFinderAlarmListener implements AlarmListener {
    private volatile boolean aborted;
    private int count;
    private long num;
    private long result;

    public PrimeFinderAlarmListener(long startingValue) {
        num = startingValue;
    }

    public void abort() {
        aborted = true;
    }

    public void fired(Alarm alarm) {
        while (!isPrime(num))
            if (aborted || Thread.currentThread().isInterrupted())
                throw new RuntimeException(new InterruptedException());
            else
                num++;
        result = num++;
        // optionally reschedule:
        Object delays = alarm.getContext();
        if (delays instanceof Integer)
            alarm.reset((Integer) delays);
        else if (delays instanceof int[] && count < ((int[]) delays).length)
            alarm.reset(((int[]) delays)[count++]);
    }

    public long getPrimeNumber() {
        if (result > 0)
            return result;
        else
            throw new IllegalStateException();
    }

Exemple de tâche TimerListener pour les Asynchronous beans qui recherche le nombre premier suivant :

public class PrimeFinderTimerListener implements CancelTimerListener, TimerListener {
    private volatile boolean aborted;
    private int count;
    private final long[] delays;
    private long num;
    private long result;

    public PrimeFinderTimerListener(long startingValue, long... delays) {
        num = startingValue;
        this.delays = delays;
    }

    public void timerCancel(Timer timer) {
        aborted = true;
    }

    public void timerExpired(Timer timer) {
        while (!isPrime(num))
            if (aborted || Thread.currentThread().isInterrupted())
                throw new RuntimeException(new InterruptedException());
            else
                num++;
        result = num++;
        // optionally reschedule:
        if (count < delays.length)
            try { 
                TimerManager timerManager = (TimerManager) new InitialContext().lookup(
                    "java:comp/env/tm/default");
                timerManager.schedule(this, delays[count++]);
            } catch (NamingException x) {
                throw new RuntimeException(x);
            }
    }

    public long getPrimeNumber() {
        if (result > 0)
            return result;
        else
            throw new IllegalStateException();
    }
}

Exemple de tâche Runnable pour Concurrency Utilities for Java EE qui recherche le nombre premier suivant :

public class PrimeFinderRunnable implements Runnable {
    private long num;
    private long result;

    public PrimeFinderRunnable(long startingValue) {
        num = startingValue;
    }

    public void run() {
        while (!isPrime(num))
            if (Thread.currentThread().isInterrupted())
                throw new RuntimeException(new InterruptedException());
            else
                num++;
        result = num++;
    }

    public long getPrimeNumber() {
        if (result > 0)
            return result;
        else
            throw new IllegalStateException();
    }
}

Exemple de tâche Callable pour Concurrency Utilities for Java EE qui recherche le nombre premier suivant :

public class PrimeFinderTask implements Callable<Long> {
    private long num;

    public PrimeFinderTask(long startingValue) {
        num = startingValue;
    }

    public Long call() throws InterruptedException {
        while (!isPrime(num))
            if (Thread.currentThread().isInterrupted())
                throw new InterruptedException();
            else
                num++;
        return num++;
    }
}

Exemple de tâche Work pour Asynchronous beans qui effectue une insertion de base de données de base :

public class DBInsertWorkAB implements Work, Serializable {
    private static final long serialVersionUID = 2606824039439594442L;
    private transient Thread executionThread;
    private final String code;
    private final String name;
    private boolean released;
    private volatile int result = -1;

    public DBInsertWorkAB(String code, String name) {
        this.code = code;
        this.name = name;
    }

    public int getResult() {
        return result;
    }

    public synchronized void release() {
        released = true;
        if (executionThread != null)
            executionThread.interrupt();
    }

    public void run() {
	synchronized (this) {
            if (released)
                throw new RuntimeException("Work was canceled");
            executionThread = Thread.currentThread();
        }
        try {
            DataSource ds = (DataSource) new InitialContext().lookup(
                "java:app/env/jdbc/dsRef");
            Connection con = ds.getConnection();
            try {
                PreparedStatement stmt = con.prepareStatement(
                    "INSERT INTO AIRPORTS VALUES(?,?)");
                stmt.setString(1, code);
                stmt.setString(2, name);
                result = stmt.executeUpdate();
            } finally {
                con.close();
            }
        } catch (NamingException x) {
            throw new RuntimeException(x);
        } catch (SQLException x) {
            throw new RuntimeException(x);
        } finally {
            synchronized (this) {
                executionThread = null;
            }
        }
    }
}

Exemple de tâche AlarmListener pour Asynchronous beans qui effectue une insertion de base de données de base :

public class DBInsertAlarmListener implements AlarmListener {
    private volatile int result = -1;

    public int getResult() {
        return result;
    }

    public void fired(Alarm alarm) {
        String[] alarmContext = (String[]) alarm.getContext();
        try {
            DataSource ds = (DataSource) new InitialContext().lookup(
                "java:app/env/jdbc/dsRef");
            Connection con = ds.getConnection();
            try {
                PreparedStatement stmt = con.prepareStatement(
                    "INSERT INTO AIRPORTS VALUES(?,?)");
                stmt.setString(1, alarmContext[0]);
                stmt.setString(2, alarmContext[1]);
                result = stmt.executeUpdate();
            } finally {
                con.close();
            }
        } catch (NamingException x) {
            throw new RuntimeException(x);
        } catch (SQLException x) {
            throw new RuntimeException(x);
        }
    }
}

Exemple de tâche Work pour CommonJ qui effectue une insertion de base de données de base :

public class DBInsertWorkCJ implements Work, Serializable {
    private static final long serialVersionUID = -8801347489043041978L;
    private transient Thread executionThread;
    private final String code;
    private final String name;
    private boolean isDaemon;
    private boolean released;
    private volatile int result = -1;

    public DBInsertWorkCJ(String code, String name) {
        this.code = code;
        this.name = name;
    }

    public int getResult() {
        return result;
    }

    public boolean isDaemon() {
        return isDaemon;
    }

    public synchronized void release() {
        released = true;
        if (executionThread != null)
            executionThread.interrupt();
    }

    public void run() {
	synchronized (this) {
            if (released)
                throw new RuntimeException("Work was canceled");
            executionThread = Thread.currentThread();
        }
        try {
            DataSource ds = (DataSource) new InitialContext().lookup(
                "java:app/env/jdbc/dsRef");
            Connection con = ds.getConnection();
            try {
                PreparedStatement stmt = con.prepareStatement(
                    "INSERT INTO AIRPORTS VALUES(?,?)");
                stmt.setString(1, code);
                stmt.setString(2, name);
                result = stmt.executeUpdate();
            } finally {
                con.close();
            }
        } catch (NamingException x) {
            throw new RuntimeException(x);
        } catch (SQLException x) {
            throw new RuntimeException(x);
        } finally {
            synchronized (this) {
                executionThread = null;
            }
        }
    }

Exemple de tâche TimerListener pour CommonJ qui effectue une insertion de base de données de base :

public class DBInsertTimerListener implements TimerListener {
    private volatile int result = -1;

    private final String code;
    private final String name;

    public DBInsertTimerListener(String code, String name) {
        this.code = code;
        this.name = name;
    }

    public int getResult() {
        return result;
    }

    public void timerExpired(Timer timer) {
        try {
            DataSource ds = (DataSource) new InitialContext().lookup(
                "java:app/env/jdbc/dsRef");
            Connection con = ds.getConnection();
            try {
                PreparedStatement stmt = con.prepareStatement(
                    "INSERT INTO AIRPORTS VALUES(?,?)");
                stmt.setString(1, code);
                stmt.setString(2, name);
                result = stmt.executeUpdate();
            } finally {
                con.close();
            }
        } catch (NamingException x) {
            throw new RuntimeException(x);
        } catch (SQLException x) {
            throw new RuntimeException(x);
        }
    }
}

Exemple de tâche Callable pour Concurrency Utilities for Java EE qui effectue une insertion de base de données de base :

public class DBInsertTask implements Callable<Integer>, Serializable {
    private static final long serialVersionUID = 5556464104788801400L;
    private final String code;
    private final String name;

    public DBInsertTask(String code, String name) {
        this.code = code;
        this.name = name;
    }

    public Integer call() throws NamingException, SQLException {
        DataSource ds = (DataSource) new InitialContext().lookup(
            "java:app/env/jdbc/dsRef");
        Connection con = ds.getConnection();
        try {
            PreparedStatement stmt = con.prepareStatement(
                "INSERT INTO AIRPORTS VALUES(?,?)");
            stmt.setString(1, code);
            stmt.setString(2, name);
            return stmt.executeUpdate();
        } finally {
            con.close();
        }
    }
}

Soumission d'une tâche

Les trois modèles de programmation fournisse un moyen de soumettre une tâche de base à exécuter sur une unité d'exécution de pool et obtenir le résultat.

Exemple Asynchronous beans :

WorkItem workItem = abWorkManager.startWork(
    new DBInsertWorkAB("DLH", "Duluth International Airport"));
ArrayList<WorkItem> items = new ArrayList<WorkItem>(1);
items.add(workItem);
if (abWorkManager.join(items, WorkManager.JOIN_AND, TIMEOUT_MS)) {
    DBInsertWorkAB work = (DBInsertWorkAB) workItem.getResult();
    int numUpdates = work.getResult();
}

Exemple CommonJ :

WorkItem workItem = cjWorkManager.schedule(
    new DBInsertWorkCJ("HIB", "Chisholm-Hibbing Airport"));
if (cjWorkManager.waitForAll(Collections.singletonList(workItem), TIMEOUT_MS)) {
    DBInsertWorkCJ work = (DBInsertWorkCJ) workItem.getResult();
    int numUpdates = work.getResult();
}

Exemple Concurrency Utilities for Java EE :

Future<Integer> future = executor.submit(
    new DBInsertTask("INL", "Falls International Airport"));
int numUpdates = future.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);

Options supplémentaires lors de la soumission d'une tâche

Lors de la soumission d'une tâche, vous avez la possibilité d'affecter un programme d'écoute et un délai d'attente au démarrage et d'indiquer si l'exécution est prévue pour une exécution longue. Le délai d'attente au démarrage est disponible uniquement comme paramètres dans Asynchronous beans, mais pour CommonJ et Concurrency Utilities for Java EE il est possible d'implémenter un délai d'attente au démarrage dans WorkListener ou ManagedTaskListener.

Exemple Asynchronous beans :

long startTimeout = TIMEOUT_MS;
boolean isLongRunning = true;
WorkItem workItem = abWorkManager.startWork(
    new DBInsertWorkAB("SGS", "South Saint Paul Municipal Airport"),
    startTimeout,
    new WorkListenerAB(),
    isLongRunning);
ArrayList<WorkItem> items = new ArrayList<WorkItem>(1);
items.add(workItem);
if (abWorkManager.join(items, WorkManager.JOIN_AND, Integer.MAX_VALUE)) {
    DBInsertWorkAB work = (DBInsertWorkAB) workItem.getResult();
    int numUpdates = work.getResult();
}

Exemple CommonJ :

long startTimeout = TIMEOUT_MS;
boolean isLongRunning = true;
DBInsertWorkCJ work = new DBInsertWorkCJ("STP", "Saint Paul Downtown Airport");
work.setDaemon(isLongRunning);
WorkItem workItem = cjWorkManager.schedule(
    work, new WorkListenerCJ(work, startTimeout));
Collection<WorkItem> items = Collections.singleton(workItem);
if (cjWorkManager.waitForAll(items, WorkManager.INDEFINITE)) {
    work = (DBInsertWorkCJ) workItem.getResult();
    int numUpdates = work.getResult();
}

Exemple Concurrency Utilities for Java EE :

long startTimeout = TIMEOUT_MS;
boolean isLongRunning = true;
Callable<Integer> contextualTask = ManagedExecutors.managedTask(
    new DBInsertTask("LVN", "Airlake Airport"),
    Collections.singletonMap(ManagedTask.LONGRUNNING_HINT,
        Boolean.toString(isLongRunning)),
    new TaskListener(startTimeout));
Future<Integer> future = executor.submit(contextualTask);
int numUpdates = future.get();

Attente de fin d'exécution d'un groupe de tâches

Les trois modèles de programmation fournissent des moyens d'attendre la fin d'exécution d'un groupe de tâches. Les exemples suivants spécifient une durée maximale de temps d'attente. Il est possible d'attendre indéfiniment ou d'utiliser Concurrency Utilities for Java EE pour exécuter get de manière séquentielle sur les variables future.

ArrayList<WorkItem> items = new ArrayList<WorkItem>(3);
items.add(abWorkManager.startWork(
    new DBInsertWorkAB("COQ", "Cloquet/Carlton County Airport")));
items.add(abWorkManager.startWork(
    new DBInsertWorkAB("CQM", "Cook Municipal Airport")));
items.add(abWorkManager.startWork(
    new DBInsertWorkAB("CKN", "Crookston Municipal Airport")));
boolean allCompleted = abWorkManager.join(items, WorkManager.JOIN_AND, TIMEOUT_MS);
int numUpdates = 0;
for (WorkItem workItem : items) {
    if (workItem.getStatus() == WorkEvent.WORK_COMPLETED) {
        DBInsertWorkAB work = (DBInsertWorkAB) workItem.getResult();
        numUpdates += work.getResult();
    } else
        ((Work) workItem.getEventTrigger(Work.class)).release();
}

Exemple CommonJ :

List<DBInsertWorkCJ> workList = Arrays.asList(
    new DBInsertWorkCJ("DTL", "Detroit Lakes Airport"),
    new DBInsertWorkCJ("TOB", "Dodge Center Airport"),
    new DBInsertWorkCJ("DYT", "Sky Harbor Airport"));
List<WorkItem> items = new ArrayList<WorkItem>(workList.size());
for (DBInsertWorkCJ work : workList)
    items.add(cjWorkManager.schedule(work));
boolean allCompleted = cjWorkManager.waitForAll(items, TIMEOUT_MS);
int numUpdates = 0;
for (int i = 0; i < items.size(); i++) {
    WorkItem workItem = items.get(i); 
    if (workItem.getStatus() == WorkEvent.WORK_COMPLETED) {
        DBInsertWorkCJ work = (DBInsertWorkCJ) workItem.getResult();
        numUpdates += work.getResult();
    } else
        workList.get(i).release();
}

Exemple Concurrency Utilities for Java EE :

List<DBInsertTask> tasks = Arrays.asList(
    new DBInsertTask("CFE", "Buffalo Municipal Airport"),
    new DBInsertTask("CHU", "Caledonia-Houston County Airport"),
    new DBInsertTask("CBG", "Cambridge Municipal Airport"));
int numUpdates = 0;
List<Future<Integer>> futures = executor.invokeAll(tasks, TIMEOUT_MS, TimeUnit.MILLISECONDS);
for (Future<Integer> future : futures)
    numUpdates += future.get();

Attente de fin d'exécution d'une tâche unique au sein d'un groupe

Les trois modèles de programmation fournissent des moyens d'attendre la fin d'exécution d'une tâche unique au sein d'un groupe. Les exemples suivants spécifient une durée maximale de temps d'attente, mais il est également possible d'attendre indéfiniment.

Exemple Asynchronous beans :

ArrayList<WorkItem> items = new ArrayList<WorkItem>(3);
items.add(abWorkManager.startWork(new PrimeFinderWork(20)));
items.add(abWorkManager.startWork(new PrimeFinderWork(50)));
items.add(abWorkManager.startWork(new PrimeFinderWork(80)));
boolean anyCompleted = abWorkManager.join(items, WorkManager.JOIN_OR, TIMEOUT_MS);
long prime = -1;
for (WorkItem workItem : items) {
    if (workItem.getStatus() == WorkEvent.WORK_COMPLETED) {
        PrimeFinderWork work = (PrimeFinderWork) workItem.getResult();
        prime = work.getPrimeNumber();
    } else
        ((Work) workItem.getEventTrigger(Work.class)).release();
}

Exemple CommonJ :

List<PrimeFinderWork> workList = Arrays.asList(
    new PrimeFinderWork(20),
    new PrimeFinderWork(50),
    new PrimeFinderWork(80));
List<WorkItem> items = new ArrayList<WorkItem>(workList.size());
for (PrimeFinderWork work : workList)
    items.add(cjWorkManager.schedule(work));
Collection<WorkItem> completedItems = cjWorkManager.waitForAny(items, TIMEOUT_MS);
long prime = -1;
for (int i = 0; i < items.size(); i++) {
    WorkItem workItem = items.get(i);
    if (completedItems.contains(workItem)) {
        PrimeFinderWork work = (PrimeFinderWork) workItem.getResult();
        prime = work.getPrimeNumber();
    } else
        workList.get(i).release();
}

Exemple Concurrency Utilities for Java EE :

List<PrimeFinderTask> tasks = Arrays.asList(
    new PrimeFinderTask(20),
    new PrimeFinderTask(50),
    new PrimeFinderTask(80));
long prime = executor.invokeAny(tasks, TIMEOUT_MS, TimeUnit.MILLISECONDS);

Obtention de l'exception source en cas d'échec d'une tâche

Les trois modèles de programmation fournissent des moyens d'obtenir l'exception source quand l'exécution d'une tâche échoue. Cette opération peut être effectuée à l'aide de programmes d'écoute (exemples fournis plus loin) ou au moment de l'obtention du résultat de tâche, via WorkItem ou Future. Une exception WorkException ou ExecutionException est générée, contenant comme cause l'exception d'origine.

Exemple Asynchronous beans :

boolean isLongRunning = false;
WorkItem workItem = abWorkManager.startWork(
    new DBInsertWorkAB("KADC", "Wadena Municipal Airport"),
    isLongRunning);
Throwable exception = null;
ArrayList<WorkItem> items = new ArrayList<WorkItem>(1);
items.add(workItem);
if (abWorkManager.join(items, WorkManager.JOIN_AND, TIMEOUT_MS))
    try {
        DBInsertWorkAB work = (DBInsertWorkAB) workItem.getResult();
        int numUpdates = work.getResult();
    } catch (WorkException x) {
        exception = x.getCause();
    }

Exemple CommonJ :

boolean isLongRunning = false;
DBInsertWorkCJ work = new DBInsertWorkCJ("KBDH", "Willmar Municipal Airport");
work.setDaemon(isLongRunning);
WorkItem workItem = cjWorkManager.schedule(work);
Throwable exception = null;
if (cjWorkManager.waitForAll(Collections.singleton(workItem), TIMEOUT_MS))
    try {
        work = (DBInsertWorkCJ) workItem.getResult();
        int numUpdates = work.getResult();
    } catch (WorkException x) {
        exception = x.getCause();
    }

Exemple Concurrency Utilities for Java EE :

boolean isLongRunning = false;
Callable<Integer> task = ManagedExecutors.managedTask(
    new DBInsertTask("KACQ", "Waseca Municipal Airport"),
    Collections.singletonMap(ManagedTask.LONGRUNNING_HINT,
        Boolean.toString(isLongRunning)),
    null);
Future<Integer> future = executor.submit(task);
Throwable exception = null;
try {
    int numUpdates = future.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
} catch (ExecutionException x) {
    exception = x.getCause();
}

Planification d'une tâche à exécution unique après un intervalle donné

Les trois modèles de programmation fournisse un moyen de planifier une tâche de base à exécuter sur une unité d'exécution de pool à un moment dans le futur et obtenir le résultat.

Exemple Asynchronous beans :

AsynchScope asynchScope = abWorkManager.findOrCreateAsynchScope("MyScope");
AlarmManager alarmManager = asynchScope.getAlarmManager();
Alarm alarm = alarmManager.create(
    new DBInsertAlarmListener(),
    new String[] { "MSP", "Minneapolis-Saint Paul International Airport"},
    (int) TimeUnit.SECONDS.toMillis(1));
DBInsertAlarmListener alarmListener = (DBInsertAlarmListener) alarm.getAlarmListener();
// Poll for result to appear
for (long start = System.nanoTime();
    alarmListener.getResult() < 0 && System.nanoTime() - start < TIMEOUT_NS;
    Thread.sleep(200)) ;
int numUpdates = alarmListener.getResult();

Exemple CommonJ :

Timer timer = timerManager.schedule(
    new DBInsertTimerListener("STC", "Saint Cloud Regional Airport"),
    TimeUnit.SECONDS.toMillis(1));
DBInsertTimerListener timerListener = (DBInsertTimerListener) timer.getTimerListener();
// Poll for result to appear
for (long start = System.nanoTime();
    timerListener.getResult() < 0 && System.nanoTime() - start < TIMEOUT_NS;
    Thread.sleep(200)) ;
int numUpdates = timerListener.getResult();

Exemple Concurrency Utilities for Java EE :

ScheduledFuture<Integer> future = executor.schedule(
    new DBInsertTask("RST", "Rochester International Airport"),
    1,
    TimeUnit.SECONDS);
int numUpdates = future.get(TIMEOUT_NS, TimeUnit.NANOSECONDS);

Planification d'une tâche répétitive à intervalle fixe et interrogation de l'intervalle jusqu'à l'exécution suivante

Les modèles de programmation CommonJ et Concurrency Utilities for Java EE fournissent un moyen de planifier une tâche répétitive pour qu'elle s'exécute à intervalle fixe (par exemple, toutes les heures, en début d'heure). La planification en temps réel n'est pas garantie. La tâche peut commencer à tout moment après cette heure, mais pas plus tôt. Les modèles de programmation CommonJ et Concurrency Utilities for Java EE fournissent également une méthode de simplification du calcul du délai d'attente jusqu'à la prochaine exécution.

Exemple CommonJ :

Timer timer = timerManager.scheduleAtFixedRate(
    new PrimeFinderTimerListener(120),
    TimeUnit.MINUTES.toMillis(90),
    TimeUnit.MINUTES.toMillis(30));
long nextExecTime = timer.getScheduledExecutionTime();
long delay = TimeUnit.MILLISECONDS.toSeconds(
    nextExecTime - System.currentTimeMillis());

Exemple Concurrency Utilities for Java EE :

ScheduledFuture<?> future = executor.scheduleAtFixedRate(
    new PrimeFinderRunnable(120), 90, 30, TimeUnit.MINUTES);
long delay = future.getDelay(TimeUnit.SECONDS);

Planification d'une tâche répétitive avec un temps d'attente fixe entre les exécutions et l'annulation de la tâche

Les modèles de programmation CommonJ et Concurrency Utilities for Java EE fournissent un moyen de planifier une tâche répétitive pour qu'elle s'exécute à intervalle fixe entre la fin d'une exécution et le début de l'exécution suivante. La planification en temps réel n'est pas garantie. La tâche peut commencer à tout moment après cette heure, mais pas plus tôt. Les beans asynchrones (Asynchronous beans) fournissent une méthode de réinitialisation sur Alarm qui peut être utilisée pour obtenir le même comportement. Les trois modèles de programmation fournissent un moyen d'annuler les exécutions supplémentaires d'une tâche planifiée depuis le début.

Exemple Asynchronous beans :

AsynchScope asynchScope = abWorkManager.findOrCreateAsynchScope("MyScope");
AlarmManager alarmManager = asynchScope.getAlarmManager();
Alarm alarm = alarmManager.create(
    new PrimeFinderAlarmListener(90), 50, 10);
// ... eventually cancel the alarm
alarm.cancel();

Exemple CommonJ :

Timer timer = timerManager.schedule(
    new PrimeFinderTimerListener(90), 50, 50);
// ... eventually cancel the timer
timer.cancel();

Exemple Concurrency Utilities for Java EE :

ScheduledFuture<?> future = executor.scheduleWithFixedDelay(
    new PrimeFinderRunnable(90), 50, 50, TimeUnit.MILLISECONDS);
// ... eventually cancel the task
future.cancel(false);

Planification d'une tâche répétitive pour exécution à différents intervalles

Il est possible dans les trois modèles de programmation de calculer pour chaque exécution l'intervalle au bout duquel une tâche répétitive sera répétée. L'API Asynchronous beans fournit une méthode de réinitialisation pour les alarmes. Concurrency Utilities for Java EE permet de brancher un déclencheur qui va calculer l'heure de la prochaine exécution. CommonJ ne fournit aucune de ces solutions, mais il est possible, depuis CommonJ et les autres modèles de programmation, de replanifier la tâche une fois l'exécution précédente terminée. Dans les exemples suivants, une tâche est planifiée pour s'exécuter précisément quatre fois, avec des temps d'attente différents avant chaque exécution. Le code pour réinitialiser, replanifier ou calculer la prochaine exécution se trouve dans le déclencheur inclus dans cette section et les implémentations AlarmListener et TimerListener, incluses dans la section Implémentation de tâches de base.

Exemple Asynchronous beans :

int initialDelay = 50;
int[] subsequentDelays = new int[] { 40, 80, 70 };
AsynchScope asynchScope = abWorkManager.findOrCreateAsynchScope("MyScope");
AlarmManager alarmManager = asynchScope.getAlarmManager();
Alarm alarm = alarmManager.create(
    new PrimeFinderAlarmListener(60),
    subsequentDelays,
    initialDelay);
Thread.sleep(5000);
PrimeFinderAlarmListener alarmListener =
    (PrimeFinderAlarmListener) alarm.getAlarmListener();
long prime = alarmListener.getPrimeNumber();

Exemple CommonJ :

long initialDelay = 50;
long [] subsequentDelays = new long[] { 40, 80, 70 };
Timer timer = timerManager.schedule(
    new PrimeFinderTimerListener(60, subsequentDelays),
    initialDelay);
Thread.sleep(5000);
PrimeFinderTimerListener timerListener = (PrimeFinderTimerListener) timer.getTimerListener();
long prime = timerListener.getPrimeNumber();

Exemple Concurrency Utilities for Java EE :

ScheduledFuture<Long> future = executor.schedule(
    new PrimeFinderTask(60),
    new DelayTrigger(50, 40, 80, 70));
Thread.sleep(5000);
long prime = future.get();

public class DelayTrigger implements Trigger {
    private int count;
    private long[] delays;
    volatile boolean isSuspended;

    public DelayTrigger(long... delays) {
        this.delays = delays;
    }

    public Date getNextRunTime(LastExecution previousExecution, Date taskScheduledTime) {
        if (delays.length > count)
            return new Date(System.currentTimeMillis() + delays[count++]);
        else
            return null;
    }

    public boolean skipRun(LastExecution previousExecution, Date scheduledRunTime) {
        return isSuspended;
    }
}

Interruption et reprise de l'exécution de tâches

CommonJ TimerManager fournit des interfaces pour interrompre et reprendre l'exécution des tâches. Concurrency Utilities for Java EE fournit cette fonction sur une base inférieure de granularité, via la méthode skipRun du mécanisme de déclencheur connectable. Une instance de déclencheur unique peut être fournie à tout nombre de tâches, dans la mesure où le déclencheur es implémenté pour prendre en charge l'opération. Dans l'exemple suivant, le déclencheur est écrit pour être utilisé pour la planification d'une tâche unique.

Exemple CommonJ :

Timer timer = timerManager.schedule(
    new PrimeFinderTimerListener(100),
    new Date(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(5)));
timerManager.suspend();
// ... resume at a later point
if (timerManager.isSuspending() || timerManager.isSuspended())
    timerManager.resume();

Exemple Concurrency Utilities for Java EE :

DelayTrigger trigger = new DelayTrigger(
    System.currentTimeMillis() + TimeUnit.DAYS.toMillis(5));
ScheduledFuture<Long> future = executor.schedule(
    new PrimeFinderTask(100), trigger);
trigger.isSuspended = true;
// ... resume at a later point
if (trigger.isSuspended)
    trigger.isSuspended = false;

Arrêt des exécutions suivantes de tâches

Les beans asynchrones (Asynchronous beans) fournissent un moyen de détruire AsynchScope, ce qui annule toutes les alarmes créées par AlarmManagers dans cette portée. CommonJ TimerManager fournit des interfaces pour empêcher les exécutions ultérieures de démarrer et attendre l'arrêt de toutes les tâches en cours d'exécution. Cette opération est possible car chaque consultation d'un TimerManager produit une nouvelle instance, laquelle peut être arrêtée indépendamment des autres. Dans Concurrency Utilities for Java EE, le même service ManagedScheduledExecutorService est partagé par les recherches, et les opérations de cycle de vie telles que shutdown, isTerminated et awaitTermination ne sont pas autorisées (par spécification). Toutefois, Concurrency Utilities for Java EE permet d'obtenir un comportement similaire en fournissant une fabrique ManagedThreadFactory à un service ScheduledExecutorService non géré.

Exemple Asynchronous beans :

alarmManager.create(
    new PrimeFinderAlarmListener(100),
    null,
    (int) TimeUnit.HOURS.toMillis(1));
alarmManager.create(
    new PrimeFinderAlarmListener(200),
    null,
    (int) TimeUnit.HOURS.toMillis(2));
// ... eventually destroy the asynch scope to cancel all alarms
asynchScope.destroy();

Exemple CommonJ :

TimerManager timerManager = (TimerManager) new InitialContext().lookup(
    "java:comp/env/tm/default");
timerManager.schedule(
    new PrimeFinderTimerListener(100),
    new Date(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1)));
timerManager.schedule(
    new PrimeFinderTimerListener(200),
    new Date(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(2)));
// ... eventually stop the timer manager
timerManager.stop();
if (!timerManager.isStopped())
    timerManager.waitForStop(TIMEOUT_MS);

Exemple Concurrency Utilities for Java EE :

ScheduledExecutorService executor =
    Executors.newScheduledThreadPool(1, threadFactory);
executor.schedule(new PrimeFinderTask(100), 1, TimeUnit.HOURS);
executor.schedule(new PrimeFinderTask(200), 2, TimeUnit.HOURS);
// .. eventually shut down the executor
executor.shutdown();
if (!executor.isTerminated())
    executor.awaitTermination(TIMEOUT_MS, TimeUnit.MILLISECONDS);

Construction de proxys contextuels

Les modèles de programmation Asynchronous beans et Concurrency Utilities for Java EE permettent de construire des proxys contextuels. Le contexte d'unité d'exécution est capturé à partir de l'unité d'exécution qui crée le proxy contextuel et il est stocké dedans, étant appliqué automatiquement à l'unité d'exécution de l'exécution quand des méthodes d'interface sont appelées sur le proxy et ensuite, lorsqu'elles sont retirées de l'unité d'exécution de l'exécution. Les beans asynchrones (Asynchronous beans) fournissent cette fonction via EventSource. Concurrency Utilities for Java EE fournit cette fonction via ContextService.

Exemple Asynchronous beans :

EventSource eventSource = abWorkManager.createEventSource();
eventSource.addListener(new DBWriterImpl());
DBWriter dbWriter = (DBWriter) eventSource.getEventTrigger(DBWriter.class);
// Can invoke interface methods from any thread...
int numUpdates = dbWriter.exec(
    "INSERT INTO AIRPORTS VALUES(?,?)", "AIT", "Aitkin Municipal Airport");

Exemple Concurrency Utilities for Java EE :

DBWriter dbWriter = contextService.createContextualProxy(
    new DBWriterImpl(), DBWriter.class);
// Can invoke interface methods from any thread...
int numUpdates = dbWriter.exec(
    "INSERT INTO AIRPORTS VALUES(?,?)", "AXN", "Alexandria Municipal Airport");

Construction de proxys contextuels pour plusieurs instances s'exécutant dans la transaction de l'unité d'exécution

Asynchronous beans et Concurrency Utilities for Java EE permettent tous deux d'indiquer si des méthodes d'interface du proxy contextuel sont exécutées dans la transaction de l'unité d'exécution ou si la transaction en cours est interrompue et un contexte de transaction nettoyé est appliqué lors de la méthode. Autre fonction d'Asynchronous beans : permet à plusieurs instances de programme d'écoute d'être déclenchées par un proxy unique. Toutefois, Concurrency Utilities for Java EE ne dispose pas de cette fonction et un comportement analogue peut être obtenu en écrivant programme d'écoute encapsuleur qui délègue à plusieurs autres. L'exemple suivant appelle un proxy unique qui déclenche plusieurs instances de programme d'écoute, tous sous la transaction de l'unité d'exécution appelante.

Exemple Asynchronous beans :

boolean runInSameTran = true;
EventSource eventSource = abWorkManager.createEventSource();
eventSource.addListener(new DBInsertTask("MKT", "Mankato Regional Airport"));
eventSource.addListener(new DBInsertTask("ULM", "New Ulm Municipal Airport"));
eventSource.addListener(new DBInsertTask("OWA", "Owatonna Degner Regional Airport"));
Callable<?> eventTrigger = (Callable<?>) eventSource.getEventTrigger(
    Callable.class, runInSameTran);
// Can invoke interface methods from any thread...
tran.begin();
try {
    eventTrigger.call();
} finally {
    tran.commit();
}

Exemple Concurrency Utilities for Java EE :

Callable<?> eventTrigger = contextService.createContextualProxy(
    new Callable<Void>() {
        @Override
        public Void call() throws Exception {
            new DBInsertTask("FFM", "Fergus Falls Municipal Airport").call();
            new DBInsertTask("ONA", "Winona Municipal Airport").call();
            new DBInsertTask("OTG", "Worthington Municipal Airport").call();
            return null;
        }
    },
    Collections.singletonMap(ManagedTask.TRANSACTION,
        ManagedTask.USE_TRANSACTION_OF_EXECUTION_THREAD),
    Callable.class);
// Can invoke interface methods from any thread...
tran.begin();
try {
    eventTrigger.call();
} finally {
    tran.commit();
}

Création de tâches contextuelles pour l'exécution différée de l'unité d'exécution appelante

Les beans asynchrones (Asynchronous beans) permettent de créer un contexte WorkWithExecutionContext, qui est essentiellement un proxy contextuel sérialisable pour un tâche, laquelle peut être ultérieurement soumise à un gestionnaire de travail (WorkManager) pour exécution sous le contexte de l'unité d'exécution à l'origine de la création. Si l'intention est une exécution sous l'unité d'exécution appelante (méthode doWork de WorkManager), un proxy contextuel peut accomplir un comportement analogue dans Concurrency Utilities for Java EE.

Exemple Asynchronous beans :

WorkWithExecutionContext contextualWork = abWorkManager.create(
    new DBInsertWorkAB("BJI", "Bemidji Regional Airport"));
// Can run the contextual work on any thread...
abWorkManager.doWork(contextualWork);
DBInsertWorkAB work = (DBInsertWorkAB) contextualWork.getWork();
int numUpdates = work.getResult();

Exemple Concurrency Utilities for Java EE :

Callable<Integer> contextualTask = contextService.createContextualProxy(
    new DBInsertTask("BRD", "Brainerd Lakes Regional Airport"),
    Callable.class);
// Can run the contextual proxy on any thread...
int numUpdates = contextualTask.call();

Création de tâches contextuelles pour exécution différée sur une unité d'exécution en pool

Les beans asynchrones (Asynchronous beans) permettent de créer un contexte WorkWithExecutionContext, qui est essentiellement un proxy contextuel sérialisable pour un tâche, laquelle peut être ultérieurement soumise à un gestionnaire de travail (WorkManager) pour exécution sous le contexte de l'unité d'exécution à l'origine de la création. Si l'intention est une exécution sur une unité d'exécution en pool (méthode startWork de WorkManager), un comportement analogue peut être accomplis dans Concurrency Utilities for Java EE en soumettant un proxy contextuel pour une tâche à un programme d'exécution géré, lequel est moins efficace en raison de la duplication de la capture de contexte d'unité d'exécution et de la propagation.

Exemple Asynchronous beans :

WorkWithExecutionContext contextualWork = abWorkManager.create(
    new DBInsertWorkAB("ELO", "Ely Municipal Airport"));
WorkItem workItem = abWorkManager.startWork(contextualWork);
ArrayList<WorkItem> items = new ArrayList<WorkItem>(1);
items.add(workItem);
if (abWorkManager.join(items, WorkManager.JOIN_AND, TIMEOUT_MS)) {
    DBInsertWorkAB work = (DBInsertWorkAB) workItem.getResult();
    int numUpdates = work.getResult();
}

Exemple Concurrency Utilities for Java EE :

Callable<Integer> contextualTask = contextService.createContextualProxy(
    new DBInsertTask("EVM", "Eveleth-Virginia Municipal Airport"),
    Callable.class);
Future<Integer> future = executor.submit(contextualTask);
int numUpdates = future.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);

Options supplémentaires pour des tâches contextuelles pour l'exécution différée

Lors de la soumission d'une tâche pour exécution différée, vous avez la possibilité d'affecter un programme d'écoute et un délai d'attente au démarrage et d'indiquer si l'exécution est prévue pour une exécution longue. Le délai d'attente au démarrage est disponible uniquement comme paramètres dans Asynchronous beans, mais pour CommonJ et Concurrency Utilities for Java EE il est possible d'implémenter un délai d'attente au démarrage dans WorkListener ou ManagedTaskListener.

Exemple Asynchronous beans :

long startTimeout = TIMEOUT_MS;
boolean isLongRunning = true;
WorkWithExecutionContext contextualWork = abWorkManager.create(
    new DBInsertWorkAB("FRM", "Fairmont Municipal Airport"));
WorkItem workItem = abWorkManager.startWork(
    contextualWork, startTimeout, new WorkListenerAB(), isLongRunning);
ArrayList<WorkItem> items = new ArrayList<WorkItem>(1);
items.add(workItem);
if (abWorkManager.join(items, WorkManager.JOIN_AND, Integer.MAX_VALUE)) {
    DBInsertWorkAB work = (DBInsertWorkAB) workItem.getResult();
    int numUpdates = work.getResult();
}

Exemple Concurrency Utilities for Java EE :

long startTimeout = TIMEOUT_MS;
boolean isLongRunning = true;
Callable<Integer> contextualTask = contextService.createContextualProxy(
    new DBInsertTask("FBL", "Faribault Municipal Airport"),
    Callable.class);
contextualTask = ManagedExecutors.managedTask(
    contextualTask,
    Collections.singletonMap(ManagedTask.LONGRUNNING_HINT,
        Boolean.toString(isLongRunning)),
    new TaskListener(startTimeout));
Future<Integer> future = executor.submit(contextualTask);
int numUpdates = future.get();

Surveillance des sous-systèmes

Les beans asynchrones (Asynchronous beans) fournissent SubsystemMonitor et SubsystemMonitorManager comme mécanisme de coordination des applications ou d'autres artefacts afin de surveiller la disponibilité. Concurrency Utilities for Java EE ne fournit aucune solution équivalente. Si un remplacement de cette fonction est nécessaire, vous pouvez implémenter une application connue de toutes les autres applications et qui agira en tant qu'équivalent de SubsystemMonitorManager.

Gestion des événements

Les beans asynchrones (Asynchronous beans) permettent d'enregistrer des programmes d'écoute pour différents types d'événements qui se produisent sur AlarmManager, AsynchScope, EventSource, SubsystemMonitor, WorkManager et Work. La plupart de ces événements n'ont pas d'équivalents directs dans Concurrency Utilities for Java EE. La responsabilité est laissée aux applications pour implémenter leurs propres mécanismes pour les événements et les notifications. Dans un ou deux cas, Concurrency Utilities for Java EE fournit une fonction similaire. Dans certains cas, vous pouvez utiliser ManagedTaskListener, qui est enregistré sur une base inférieure de granularité (lors de la soumission de la tâche) à la place d'événements AlarmManagerEvents et WorkEvents.

Gestion des événements pour une défaillance survenue lors de l'appel d'un proxy contextuel

Dans les beans asynchrones (Asynchronous beans), quand un proxy contextuel est utilisé pour appeler une opération et que celle-ci déclenche une exception déclarée, l'exception n'est pas signalée à l'auteur de l'appel. En revanche, elle est signalée dans l'événement listenerExceptionThrown aux programmes d'écoute EventSourceEvents. Dans Concurrency Utilities for Java EE, l'auteur de l'appel peut intercepter l'exception et la gérer.

Exemple Asynchronous beans :

EventSource eventSource = abWorkManager.createEventSource();
eventSource.addListener(new DBWriterImpl());
eventSource.addListener(new EventSourceEvents() {
    public void listenerCountChanged(
        EventSource es, int oldCount, int newCount) {}

    public void listenerExceptionThrown(
        EventSource es, Object listener,
        String methodName, Throwable exception) {
        listenerException.set(exception);
    }

    public void unexpectedException(
        EventSource es, Object runnable, Throwable exception) {}
});
DBWriter dbWriter = (DBWriter) eventSource.getEventTrigger(DBWriter.class);
// Can invoke interface methods from any thread...
try {
    dbWriter.exec(
        "INSERT INTO AIRPORTS VALUES(?,?)", "KAUM", "Austin Municipal Airport");
} catch (Exception x) {
    // expecting this to fail
}
Throwable exception = listenerException.get();

Exemple Concurrency Utilities for Java EE :

DBWriter dbWriter = contextService.createContextualProxy(
    new DBWriterImpl(), DBWriter.class);
// Can invoke interface methods from any thread...
SQLException exception = null;
try {
    dbWriter.exec(
        "INSERT INTO AIRPORTS VALUES(?,?)", "KSBU", "Blue Earth Municipal Airport");
} catch (SQLException x) {
    exception = x;
}

Icône indiquant le type de rubrique Rubrique de référence



Icône d'horodatage Dernière mise à jour: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=rasb_migrate_to_eeconcurrency
Nom du fichier : rasb_migrate_to_eeconcurrency.html