+

Search Tips   |   Advanced Search

Develop tasks to run code in parallel

We can perform operations in parallel by wrapping the code in a Callable or Runnable and then submitting or scheduling it to a manager executor.

Optionally, your administrator can use the administrative console to configure at least one work manager or to change the settings of the default work manager.

To run code in parallel, wrap the code in a Callable or Runnable and the submit or schedule it to a managed executor.


Tasks

  1. Implement a Callable or Runnable task.

    A task implements the java.util.concurrent.Callable interface or java.lang.Runnable interface. For example, we can create a task that dynamically subscribes to a topic and any component.

    class SampleTask implements Callable<Object>
    {
       Set<MessageListener> listeners =      
          Collections.newSetFromMap(new ConcurrentHashMap<MessageListener, Boolean>();
       Topic targetTopic;
       TopicConnectionFactory tcf;
    
       public SampleWork(TopicConnectionFactory tcf, Topic targetTopic)
       {
          this.targetTopic = targetTopic;
          this.tcf = tcf;
       }
    
       public void addMessageListener(MessageListener listener) 
       {
          listeners.add(listener);
       }
    
       public Object call() throws JMSException
       {
          // setup our JMS stuff.TopicConnection
          tc = tcf.createConnection();
          try
          {
             TopicSession sess = tc.createSession(false, Session.AUTOACK);
             tc.start();
             while( !Thread.currentThread().isInterrupted() )
             {
                // block for up to 5 seconds.
                Message msg = sess.receiveMessage(5000);
                if( msg != null )
                   for (MessageListener listener : listeners)
                      listener.onMessage(msg);
             }
             tc.close();
          }
          finally
          {
             if (tc != null) tc.close();
          }
          return null;
       }
    }
    

    As a result, any component can add a message listener on demand, which allows components to subscribe to a topic in a more scalable way than by simply giving each client subscriber its own thread.

  2. Determine the number of work managers needed by this application component.
  3. Look up the work manager or managers using the managed executor, thread factory, context service resource environment reference, or work manager resource reference (or logical name) in the java:comp namespace. (For more information on resource environment references and resource references, refer to the References topic.)
    InitialContext ic = new InitialContext();
    ManagedExecutorService executor = (ManagedExecutorService)ic.lookup("java:comp/env/concurrent/myWorkManager");
    
    The resource environment reference for the managed executor (in this case, concurrent/myWorkManager) must be declared as a resource environment reference in the application deployment descriptor or a @Resource annotation.
  4. Call the ManagedExecutorService.submit() method using the Callable or Runnable task instance as a parameter. For example:
    Callable<Boolean> task = new MyTask(...);
    Future<Boolean> future = executor.submit(task);
    

    The Future is a handle that provides a link from the component to the submitted task.

  5. Optional: If the application component needs to wait for one or more of its tasks to complete, call the Future.get() method. For example:
    Future<String> futureA = executor.submit(taskA);
    Future<String> futureB = executor.submit(taskB);
    futureA.get(5, TimeUnit.SECONDS);
    futureB.get(5, TimeUnit.SECONDS);
    

    Alternately, use the invokeAll() method to submit multiple tasks and wait for all of them to complete. For example:

    tasks = Arrays.asList(taskA, taskB);
    futures = executor.invokeAll(tasks, 5, TimeUnit.SECONDS);
        // we can check future.isDone() to see which, if any, finished.
    

    This method takes a collection of tasks which your component wants to wait on for all the work objects to complete. We also can specify a timeout value.

  6. Use the Future.cancel(true) method to attempt to interrupt the task.

    Implement the task to respond to the interrupt immediately or try to stop running as soon as possible.


Subtopics


Related:

  • References in application deployment descriptor files