问题
We have a requirement where in we need to monitor remote JVM details via JMX using a simple servlet application. So things done till now in a standalone application is
1) Creat a JMX connector & get the Memory data --> done 2) We need to constantly monitor & get the records (2.1 > which can be considered as scheduled task at constant delay & insert the records into DB Or 2.2> does the JMX gives the history if yes which MBean to access for the info?).
Here I am planning to use an interface to register the domain , followed to it. Have start & stop button from JSP. The functionality been when we click start the system will run the scheduler (ScheduledExecutorService ) & capture the records at background to give the history. When the uses clicks stop the scheduler has to stop the background process. The question is how can we control & get the object of a scheduler ?
1) In other words how can we start & stop a ScheduledExecutorService via servlets ? start a thread from one servlet & stop a thread from another servlet for a particular task ?
2) What if we have a clustered/load balanced environment ?
Currently am thinking of adding each ScheduledExecutorService into HashMap , key been the task object & value been the ScheduledExecutorService using SingleTon desgin pattern. Is there any default approach. The loop whole with SingleTon is in clustered/load balanced environment we may not be able to get the appropriate update objects.
Looking forward for your valuable suggestion.
回答1:
If on java ee 7, try using the javax.enterprise.concurrent.ManagedScheduledExecutorService
Then you can do a resource injection and start the task with code similiar to below.
@Resource
ManagedScheduledExecutorService mses;
public void startTask() {
mses.scheduleAtFixedRate(runnable, 10, 10, SECONDS);
}
In Java EE 6 you could have a servlet create/remove using the timerservice API
回答2:
ServletContext
A ServletContext represents your entire web app as running in the Servlet container. The context is established before the first HTTP request is processed by the servlet, as promised by the Servlet spec. While a HttpSession represents each user’s work session (technically, a thread through your servlet code), a ServletContext
represents the scope across all those users.
To hook into the set-up and tear-down of the servlet context, implement a ServletContextListener. Tip: Auto-deploy your listener by marking it with @WebListener annotation. That interface requires a pair of methods, each called when your web app is being set-up before the first Servlet request is handled and when your web app is being torn-down.
Tip: That tear-down method is a good place to shut down your ScheduledExecutorService
. The threads associated with your executor service may survive after your web app ends. You likely do not want that to happen.
See this Question: How to get and set a global object in Java servlet context
See also this nice summary of Servlet scope by BalusC.
Fetch the servlet context
You can access the current servlet’s ServletContext
by first accessing its ServletConfig.
// … in your Servlet, such as its request handler methods like `doGet` …
ServletContext sc = this.getServletConfig().getServletContext() ;
And how about in a ServletContextListener
, how do we access the servlet context? When either of the two methods on the listener is called, a ServletContextEvent is passed. From there call ServletContextEvent::getServletContext().
Store objects as ”attributes” on servlet context
So where to store your web app’s global variables such as your ScheduledExecutorService? The servlet context has a built in map of String
to Object. These are called “attributes”. Call setAttribute( String , Object ) to store an attribute mapping. So make up a name for your ScheduledExecutorService
to use a key into this map.
ScheduledExecutorService sec = … ; // Instantiated somewhere in your code.
…
String key = "myScheduledExecutorServiceForXYZ" ;
sc.setAttribute( key , sec ); // Storing the executor service as a generic `Object` for use later.
Later you can fetch your ScheduledExecutorService
in the same manner. You will need to cast from Object
to the known class, in this case ScheduledExecutorService
.
Object o = sc.getAttribute( key ); // Fetch the `ScheduledExecutorService` from the servlet context’s built-in map of attributes.
// Cast to known class. If in doubt, test first with [`instanceOf`][11].
ScheduledExecutorService sec = ( ScheduledExecutorService ) o ;
You can ask for a list of all stored attribute names by calling ServletContext::getAttributeNames.
Diagram of scope
Here is a diagram of mine to get an idea of the hierarchy of scope in a Servlet environment. Note how each layer of scope has its set of attributes, its own map of String
to Object
. As you go down the diagram, each set of attributes has a shorter lifespan.
来源:https://stackoverflow.com/questions/25237111/start-stop-a-scheduledexecutorservice-in-java-ee-environment-using-servlet