While concurrency of a singleton is container managed by default, the developer can elect to manage the concurrency directly. The techniques used for this effort are illustrated in this recipe.
The steps used to incorporate bean managed concurrency involve:
synchronized
keywordCritical methods are those methods which allow only a single thread at a time to use it.
We will reuse the ConcurrencyExample
application developed in the previous recipe to illustrate bean-managed concurrency. In the EJB module add a singleton EJB to the packt
package called SimulationBeanManaged
. Use the @ConcurrencyManagement annotation with an argument of ConcurrencyManagementType.BEAN to designate the EJB as a bean-managed EJB.
@Singleton @ConcurrencyManagement(ConcurrencyManagementType.BEAN) public class SimulationBeanManaged { public enum State {PAUSED, RUNNING, TERMINATED}; private State state; public State getState() { return state; } public synchronized void setState(State state) { this.state = state; } }
Modify the ConcurrencyServlet
servlet to use the SimulationBeanManaged
bean instead of the SimulationContainerManaged
bean. From the client perspective there is no indication of how concurrency is supported.
public class ConcurrencyServlet extends HttpServlet { @EJB SimulationBeanManaged simulationBeanManaged; protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ... simulationBeanManaged.setState( SimulationBeanManaged.State.PAUSED); ... out.println("<h3>Simulation Bean Managed State: " + simulationBeanManaged.getState() + "</h3>"); ... }
Execute the application using the URL found in the following screenshot. It will show the application in a paused state.
The SimulationBeanManaged
EJB used an enumeration to reflect the state of the application with a get and set method to control the state. The synchronized
keyword was used for the setState
method. This restricted access to the method to one client at a time. It has the same effect as the @Write annotation used with container-managed concurrency.
The getState
method is not synchronized thus allowing concurrent access to the method. For a get method, this should not be a problem since it is a read type operation.
The synchronized keyword was also be used on a block of code instead of a method. The following rewrite of the setState
method illustrates how to synchronize a block. Concurrent access is restricted when a thread enters the synchronized block. That is, no other methods are allowed to access the object while the current thread is in the block.
public void setState(State state) { synchronized (this) { this.state = state; } }
A Java compiler may use various optimization techniques to speed up the execution of an application. Some optimization techniques may move the value of a variable into a register to increase the speed of execution. However, when this occurs, changes to the original variable may not necessarily be reflected in the register. To avoid this problem the volatile
keyword was introduced. The volatile
keyword is used as part of the declaration of a class' instance variable.
private volatile int serverID;
The volatile
keyword guarantees that any thread that accesses the variable will get the most current value. When synchronizing EJB methods using bean-managed concurrency, it may be necessary to use this keyword.
18.225.234.28