Concurrency Utilities for Java
EE is being worked as JSR 236 and has
released an Early
Draft. It provides concurrency capabilities to Java
EE
application components without compromising container integrity.
Simple (common) and advanced concurrency patterns are easily
supported without sacrificing usability.
Using Java SE concurrency utilities such as java.util.concurrent
API, java.lang.Thread and java.util.Timer
in a Java
EE application component such as EJB or Servlet are
problematic since the container and server have no knowledge of
these resources. JSR 236 enables concurrency largely by extending
the Concurrency Utilities API developed under JSR-166. This also
allows a consistency between Java SE and Java
EE concurrency
programming model.
There are four main programming interfaces available:
ManagedExecutorService
ManagedScheduledExecutorService
ContextService
ManagedThreadFactory
ManagedExecutorService is a managed version of java.util.concurrent.ExecutorService.
The implementations of this interface are provided by the
container and accessible using JNDI reference:
<resource-env-ref> <resource-env-ref-name> concurrent/BatchExecutor </resource-env-ref-name> <resource-env-ref-type> javax.enterprise.concurrent.ManagedExecutorService </resource-env-ref-type><resource-env-ref>
and available as:
@Resource(name="concurrent/BatchExecutor")ManagedExecutorService executor;
Its recommended to bind the JNDI references in the java:comp/env/concurrent
subcontext.
The asynchronous tasks that need to be executed need to implement
java.lang.Runnable or java.util.concurrent.Callable
interface as:
public class MyTask implements Runnable { public void run() { // business logic goes here }}
OR
public class MyTask2 implements Callable<Date> { public Date call() { // business logic goes here }}
The task is then submitted to the executor using one of the submit
method that return a Future instance. The Future
represents the result of the task and can also be used to check if
the task is complete or wait for its completion.
Future<String> future = executor.submit(new MyTask(), String.class);. . .String result = future.get();
Another example to submit tasks is:
class MyTask implements Callback<Long> { . . . }class MyTask2 implements Callback<Date> { . . . }ArrayList<Callable> tasks = new ArrayList<();tasks.add(new MyTask());tasks.add(new MyTask2());List<Future<Object>> result = executor.invokeAll(tasks);
The ManagedExecutorService may be configured for
different properties such as:
Hung Task Threshold: Time in milliseconds that a task
can execute before it is considered hung
Pool Info
Core Size: Number of threads to keep alive
Maximum Size: Maximum number of threads allowed in
the pool
Keep Alive: Time to allow threads to remain idle when
# of threads > Core Size
Work Queue Capacity: # of tasks that can be stored in
inbound buffer
Thread Use: Application intend to run short vs
long-running tasks, accordingly pooled or daemon threads are
picked
ManagedScheduledExecutorService adds delay and
periodic task running capabilities to ManagedExecutorService.
The implementations of this interface are provided by the
container and accessible using JNDI reference:
<resource-env-ref> <resource-env-ref-name> concurrent/BatchExecutor </resource-env-ref-name> <resource-env-ref-type> javax.enterprise.concurrent.ManagedExecutorService </resource-env-ref-type><resource-env-ref>
and available as:
@Resource(name="concurrent/timedExecutor")ManagedExecutorService executor;
And then the tasks are submitted using submit, invokeXXX
or scheduleXXX methods.
ScheduledFuture<?> future = executor.schedule(new MyTask(), 5, TimeUnit.SECONDS);
This will create and execute a one-shot action that becomes
enabled after 5 seconds of delay.
More control is possible using one of the newly added methods:
MyTaskListener implements ManagedTaskListener { public void taskStarting(...) { . . . } public void taskSubmitted(...) { . . . } public void taskDone(...) { . . . } public void taskAborted(...) { . . . }
}ScheduledFuture<?> future = executor.schedule(new MyTask(), 5, TimeUnit.SECONDS, new MyTaskListener());
Here, ManagedTaskListener is used to monitor the
state of a task's future.
ManagedThreadFactory provides a method for creating
threads for execution in a managed environment. A simple usage is:
@Resource(name="concurrent/myThreadFactory")ManagedThreadFactory factory;. . .Thread thread = factory.newThread(new Runnable() { . . . });
concurrent/myThreadFactory is a JNDI resource.
There is lot of interesting content in the Early
Draft, download it, and read yourself. The implementation
will be made available soon and also be integrated in GlassFish 4
as well.
Some references for further exploring ...
Javadoc
Early
Draft Specification
concurrency-ee-spec.java.net
[email protected]