Search code examples
javamultithreadingasynchronouswebsphereworkmanagers

Websphere WorkManager join for many threads


I have one WM that starts works in some method:

public void someMethod(Params pararms){
     WorkManager wm = (WorkManager) ic.lookup(CONTROL_WORK_MANAGER);
     ArrayList<WorkItem> workItems = Lists.newArrayList();
     List<Work> works = getSomeWorks();
     for (Work work : works) {
         workItems.add(wm.startWork(work));
          }
     //after all works have been started, I just wait for them to be finished using join method:
     wm.join(workItems, WorkManager.JOIN_AND, (int) WorkManager.INDEFINITE);

    // "other code"
    }

someMethod() is called by different threads, and the problem is wm.join() doesn't wait only for given works to be completed, but for ALL the works that have been started by ALL threads. Eventually "other code" is executed when every single work in app is finished.

Is it the way it should be? If so, can I fix it, so every wm.join() waits only for "its" works to be done?

WAS version is 8.5.5.11

Thank you!


Solution

  • Per the documented behavior of WorkManager, it should be waiting for the items in the supplied list.

    https://www.ibm.com/support/knowledgecenter/SS7K4U_8.5.5/com.ibm.websphere.javadoc.doc/web/apidocs/com/ibm/websphere/asynchbeans/WorkManager.html

    Specifically, JOIN_AND is defined as "This constant is used for the ANDOR parameter of the join method to indicate that the join method should wait for all work items in the list to complete."

    The observed behavior you describe sounds like a bug, and I'll look into confirming whether I can reproduce the same.

    I'll also mention that, in the event that this behavior does turn out to be buggy and you need to replace it, one approach is to use to register a WorkListener that decrements a java.util.concurrent.CountDownLatch, which you can await from your submitter thread.

    final CountDownLatch latch = new CountDownLatch(works.size());
    WorkListener listener = new WorkListener() {
        public void workAccepted(WorkEvent we) {}
        public void workStarted(WorkEvent we) {}
        public void workCompleted(WorkEvent we) {
            latch.countDown();
        }
        public void workRejected(WorkEvent we) {
            latch.countDown();
        }
    };
    for (Work work : works) {
        workItems.add(wm.startWork(work, WorkManager.INDEFINITE, listener));
    }
    latch.await();
    

    Alternately, if you are able to move to WAS v9 for Java EE 7 support, it sounds like what you really want is javax.enterprise.concurrent.ManagedExecutorService.invokeAll() which has the combined submit & wait behavior built in.