- Java EE 7 First Look
- NDJOBO Armel Fabrice
- 1209字
- 2021-07-23 15:23:38
Concurrency Utilities for Java EE 1.0
Concurrency Utilities for Java EE 1.0 was developed under JSR 236. This section gives you only an overview of the API. The complete document specification (for more information) can be downloaded from http://jcp.org/aboutJava/communityprocess/final/jsr236/index.html.
Why concurrency?
In computer science, concurrency is the ability of an application or a system to execute many tasks in parallel. Before the advent of multitasking system, computers could only run one process at a time. At that time, the programs were not only difficult to design, but they were also executed sequentially from beginning to end and when the machine was running a program that had access to a peripheral device, the running program was first interrupted to allow the reading of the peripheral.
Benefits of concurrency
The development of multitasking operating systems enabled the simultaneous execution of many processes (instances of running programs) within a machine and many threads (also called lightweight processes; they are subsets of a process that can be run concurrently with each other) within a process. Due to this progress, it has become possible to run multiple applications at the same time, for example, listening to music and downloading a document while writing a text document.
In enterprise applications, concurrency can increase the interactivity of your program by running heavy processing asynchronously in a thread. It can also be used to improve the response time of an application by dividing a big task into smaller units that will be executed simultaneously by many threads.
Risks of concurrency
Although each thread has its proper stack of execution, it is very common to have multiple threads that share the same resources or depend on each other. In such cases, the absence of good synchronization makes threading behavior unpredictable and can degrade system performance. For example, the lack of coordination of interrelated threads can result in deadlocks and indefinitely interrupt processing.
Concurrency and Java EE
As we have seen previously, the misuse of threads can have catastrophic consequences on an application. In the case of a container, it could not only compromise its integrity, but also poorly exploit the resources provided to other components. This is one of the reasons why developers were not allowed to create threads in a container.
To enable implementation of concurrency within Java EE components, the Java EE 7 platform has integrated Concurrency Utilities. Using this API, a Java EE server can become aware of the resources that are used by threads and provide them with good execution context. Furthermore, it allows the server to manage the pool and lifecycle of threads.
Java EE Concurrency API
Concurrency Utilities for Java EE 1.0 was developed with the followings goals in mind:
- To provide a simple and flexible concurrency API to the Java EE platform without compromising the container
- To facilitate migration from Java SE to Java EE by providing consistency between the concurrency programming models
- To allow the implementation of common and advanced concurrency patterns
Concurrency Utilities was built over the Concurrency Utilities API developed under JSR-166 for Java SE (which facilitates the migration from Java SE to Java EE). It offers four main programming interfaces whose instances must be made available to application components as container-managed objects. The offered interfaces are: ContextService
, ManagedExecutorService
, ManagedScheduledExecutorService
, and ManagedThreadFactory
. All these interfaces are contained in the javax.enterprise.concurrent
package.
These four interfaces can be explained as follows:
- Managed executor service: The
ManagedExecutorService
interface extends thejava.util.concurrent.ExecutorService
interface. It allows us to submit an asynchronous task that will be run on a separate thread created and managed by the container. By default, any Java EE 7-compliant server must provide aManagedScheduledExecutorService
that can be accessed by application components under the JNDI namejava:comp/DefaultManagedScheduledExecutorService
. But, if you want to create your own, you must first declare theManagedExecutorService
resource environment reference in theweb.xml
file for a web application orejb-jar.xml
for an EJB module. The specification recommends that allManagedExecutorService
resource environment references be organized in thejava:comp/env/concurrent
subcontext.- The following configuration is an example declaration of a
ManagedExecutorService
resource environment reference:<resource-env-ref> <resource-env-ref-name> concurrent/ReportGenerator </resource-env-ref-name> <resource-env-ref-type> javax.enterprise.concurrent.ManagedExecutorService </resource-env-ref-type> </resource-env-ref>
Tip
Downloading the example code
You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.
- After declaring the JNDI reference, you can then inject it by using the
@Resource
annotation as shown in the following code:@Resource(name="concurrent/ReportGenerator") ManagedExecutorService reportGenerator;
- The task to submit to the container must either implement the
java.lang.Runnable
orjava.util.concurrent.Callable
interface. The differences between these interfaces are presented in the following table: - The following code demonstrates how to define a task that will run reports asynchronously:
public class ReportGeneratorTask implements Callable<String>{ @Override public String call() throws Exception { //generate report return "The report was generated successfully"; } }
- The following code shows us how to submit a task. We can see that the
submit()
method of theManagedExecutorService
instance returns an object of typeFuture
that will get back the result of the running task when it becomes available:Future<String> monitor = reportGenerator .submit(new ReportGeneratorTask()); String result = monitor.get();
- The following configuration is an example declaration of a
- Managed scheduled executor service: The
ManagedScheduledExecutorService
interface extends theManagedExecutorService
andjava.util.concurrent.ScheduledExecutorService
interfaces in order to execute a task at a specific time.- Instances of this interface are defined in the same way as that of the
ManagedExecutorService
interface. The following code demonstrates how to execute a task ten seconds after its submission:Future<String> monitor = reportGenerator .schedule(new ReportGeneratorTask(), 10,TimeUnit.SECONDS);
- Instances of this interface are defined in the same way as that of the
- Managed thread factory: The
ManagedThreadFactory
interface provides method to create managed thread instances in a container. The task must implement thejava.lang.Runnable
interface. The following code demonstrates how to create and run a container-managed thread.Thread myThread = threadFactory.newThread(new ReportManagedThread()); myThread.start();
- Context service: This interface allows the creation of contextual objects without using
ManagedExecutorService
orManagedScheduledExecutorService
interfaces, as we did in the previous cases, with the aim of allowing the extension of the capabilities of a Java EE platform for concurrency. Concretely, with this interface, you can create a workflow system or use customized Java SE platformExecutorService
implementations within a container. For example, if you desire to use the pool management mechanism provided by the classjava.util.concurrent.ThreadPoolExecutor
of Java SE to manage your threads in the context of a Java EE component, you will just need to combineManagedThreadFactory
,ExecutorService
, andContextService
objects. The result is as shown in the following code:public class ReportCustomizedThread implements Runnable { public void run() { //Report processing ... } } @Resource(name=?concurrent/ReportManagedThreadGenerator?) ManagedThreadFactory threadFactory; @Resource(name=?concurrent/ReportContextServiceGenerator?) ContextService contextService; ReportCustomizedThread reportThread = new ReportCustomizedThread(); Runnable proxy =contextService.createContextualProxy(reportThread,Runnable.class); ExecutorService executorService =Executors.newFixedThreadPool(20, threadFactory); Future result = executorService.submit(proxy); //...
This is probably a simple example of the use you can make of this feature. For more advanced examples, please consult the specification document in the Context service section.
The following diagram provides an overview of relationships between Concurrency Utilities and other Java EE platform elements:

Besides, it is possible to refine the configurations of different resources for better performance (for details, see the specification document), and the Concurrency Utilities for Java EE 1.0 provide many other interfaces like ManagedTaskListener
that can be used to monitor the state of a task's Future
object.