September 18, 2013

Simple Concurrency Example with Wildfly

Concurrency is the ability to run several threads in parallel, within a single process.

Since its origin Java has had java.lang.Thread for dealing with concurrency. With Java SE 5 improved support was added with the java.util.concurrency package.

Enterprise containers manage their own thread pools and ensure that the other Java EE services are available to these threads. Creating threads using the concurrency API, provided by Java SE, is not recommended in an enterprise environment as there is no guarantee that your thread would have access to these services.

By using the new Concurrency Utils you can run asynchronous operations with java.util.concurrent.ExecutorService which will result in your thread being managed by the container.

The main concurrency components are:

ManagedExecutorService - used to execute tasks in a second thread. These threads are started and managed by the container

ManagedScheduledExecutorService - Same as the ManagedExecutorService except that you can schedule the thread to start as specific times

ContextService - used for creating dynamic proxy objects

ManagedThreadFactory - used by applications to create threads that are managed by the container

Example

This example demonstrates the use of the ManagedExecutorService.

First we need to create a task object that implements Callable. Within the call() method we will define the work that we want carried out in a separate thread.

public class ReportTask implements Callable<Report> {

    Logger logger = Logger.getLogger(getClass().getSimpleName());

    public Report call() {
        try {
            Thread.sleep(3000);
        catch (InterruptedException e) {
            logger.log(Level.SEVERE, "Thread interrupted", e);
        }
    return new Report();
    }
}

Then we need to invoke the task by passing it though to the submit() method of the ManagedExecutorService.

@Stateless
public class ReportBean {

    @Resource
    private ManagedExecutorService executorService;

    public void runReports() {
        ReportTask reportTask = new ReportTask();
        Future<Report> future = executorService.submit(reportTask);
    }
}

By not specifying the lookup attribute of the @Resource annotation, Wildfly will inject a managed executor service with default configuration as configured within the ee subsystem in standalone.xml.

<subsystem xmlns="urn:jboss:domain:ee:2.0">
    <spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
    <jboss-descriptor-property-replacement>true</jboss-descriptor-property-replacement>
    <concurrent>
        <default-context-service/>
        <default-managed-thread-factory/>
        <default-managed-executor-service hung-task-threshold="60000" core-threads="5" max-threads="25" keepalive-time="5000"/>
        <default-managed-scheduled-executor-service hung-task-threshold="60000" core-threads="2" keepalive-time="3000"/>
    </concurrent>
</subsystem>


3 comments :

  1. Nice example. I added it to my personal links of the week article.

    Keep on blogging ...

    ReplyDelete
    Replies
    1. Thanks for the positive feedback. Much appreciated.

      Delete
    2. Yes keep on working !
      and thanks a lot

      Delete