I'm using Managed Executor Service to implement a service that processes background tasks. The service should be allowed to stop a running task and terminate the worker thread and return it to the threads pool for next task. Once it has been stopped, can you resume where you left off?
No, it is not possible to shutdown, terminate, or resume a ManagedExecutorService in a Java EE environment.
Per the Java EE Concurrency Utilities 1.0 spec, bullet #2
3.1.6.1 Java EE Product Provider Requirements This subsection describes additional requirements for ManagedExecutorService
providers.
All tasks, when executed from the ManagedExecutorService, will run with the Java EE component identity of the component that
submitted the task.
The lifecycle of a ManagedExecutorService is managed by an application server. All lifecycle operations on the
ManagedExecutorService interface will throw a
java.lang.IllegalStateException exception. This includes the following
methods that are defined in the java.util.concurrent.ExecutorService
interface: awaitTermination(), isShutdown(), isTerminated(),
shutdown(), and shutdownNow().
No task submitted to an executor can run if task’s component is not started.
When a ManagedExecutorService instance is being shutdown by the Java
EE Product Provider:
All attempts to submit new tasks are rejected.
All submitted tasks are cancelled if not running.
All running task threads are interrupted.
All registered ManagedTaskListeners are invoked.
This may seem like a limitation, but the reason why this restriction is in place is because the ManagedExeuctorService is managed by the Java EE Product Provider for you.
So don't worry about starting, stopping, or resuming your ManagedExeuctorService in Java EE.
Now, if you want to wait until all of your tasks are complete, that's a perfectly reasonable requirement. This can be achieved a variety of ways:
If you submit all your tasks all at once, use ExecutorService.invokeAll(java.util.Collection) and track the List> that you get back.
If you submit your tasks one at a time, use ExecutorService.submit(Callable) or ExecutorService.submit(Runnable)
Once your tasks are submitted, you will need to manage a collection of Future<T>'s in any way you choose, and use get() (blocking) or isDone() (nonblocking) to check if they are done.
Related
I have a web application that simply acts as a Front Controller using Spring Boot to call other remote REST services where I am combining Spring's DeferredResult with Observables subscribed on Scheduler.computation().
We are also using JMeter to stress out the web application, and we have noticed that requests start to fail with a 500 status, no response data and no logs anywhere when the number of concurrent threads scheduled in JMeter increases from 25, which obviously is a very "manageable" number for Tomcat.
Digging into the issue with the use of VisualVM to analyze how the threads were being created and used, we realized that the use of rx.Schedulers was somehow impacting the number of threads created by Tomcat NIO. Let me summarize our tests based on the rx.Scheduler used and a test in JMeter with 100 users (threads):
SCHEDULERS.COMPUTATION()
As we're using the Schedulers.computation() and my local machine has 4 available processors, then 4 EventLoop thread pools are created by RxJava (named RxComputationThreadPool-XXX) and ONLY 10 of Tomcat (named http-nio-8080-exec-XXX), as per VisualVM:
http://screencast.com/t/7C9La6K4Kt6
SCHEDULERS.IO() / SCHEDULERS.NEWTHREAD()
This scheduler seems to basically act as the Scheduler.newThread(), so a new thread is always created when required. Again, we can see lots of threads created by RxJava (named RxNewThreadScheduler-XXX), but ONLY 10 for Tomcat (named http-nio-8080-exec-XXX), as per VisualVM:
http://screencast.com/t/K7VWhkxci09o
SCHEDULERS.IMMEDIATE() / NO SCHEDULER
If we disable the creation of new threads in RxJava, either by setting the Schedulers.immediate() or removing it from the Observable, then we see the expected behaviour from Tomcat's threads, i.e. 100 http-nio-8080-exec corresponding to the number of users defined for the JMeter test:
http://screencast.com/t/n9TLVZGJ
Therefore, based on our testing, it's clear to us that the combination of RxJava with Schedulers and Tomcat 8 is somehow constraining the number of threads created by Tomcat... And we have no idea why or how this is happening.
Any help would be much appreciated as this is blocking our development so far.
Thanks in advance.
What is the difference between JavaFX 8 Task and Service and in which case is it better to use one over the other? What is better to use in database operations?
Main Difference between Task and Service - One Time versus Repeated Execution
A Task is a one off thing - you can only use a Task once. If you want to perform the same Task again, you need to construct a new Task instance.
A Service has a reusable interface so that you can start and restart a single service instance multiple times. Behind the scenes, it just takes a Task definition as input and creates new tasks as needed.
Example Use Cases
Task Example => monitoring and reporting progress of a long running startup task on application initialization, like this Splash Page example.
Service Example => The internal load worker implementation for WebEngine where the same task, loading a page asynchronously, needs to be repeated for each page loaded.
Recommendation - Initially try to solve your problem using only a Task and not a Service
Until you are more familiar with concurrency in JavaFX, I'd advise sticking to just using a Task rather than a Service. Tasks have a slightly simpler interface. You can accomplish most of what a Service does simply by creating new Task instances when you need them. If, after understanding Task, you find yourself wanting a predefined API for starting or restarting Tasks, then start using Service at that time.
Database Access Sample using Tasks
Either Task or Service will work for performing database operations off of the JavaFX application thread. Which to use depends on your personal coding preference as well as the particular database operation being performed.
Here is an example which uses a Task to access a database via JDBC. The example was created for JavaFX - Background Thread for SQL Query.
Background Information
The JavaFX concurrency tutorial provides a good overview of Task and Service.
There is excellent documentation in the Task and Service javadoc, including sample code for example use cases.
Worker, Task and Service definitions (from Javadoc)
Task and Service are both Workers, so they have this in common:
A Worker is an object which performs some work in one or more background threads, and whose state is observable and available to JavaFX applications and is usable from the main JavaFX Application thread.
Task definition:
A fully observable implementation of a FutureTask. Tasks expose additional state and observable properties useful for programming asynchronous tasks in JavaFX . . Because Service is designed to execute a Task, any Tasks
defined by the application or library code can easily be used with a
Service.
Service definition:
A Service is a non-visual component encapsulating the information
required to perform some work on one or more background threads. As
part of the JavaFX UI library, the Service knows about the JavaFX
Application thread and is designed to relieve the application
developer from the burden of managing multithreaded code that interacts
with the user interface. As such, all of the methods and state on the
Service are intended to be invoked exclusively from the JavaFX
Application thread.
Service implements Worker. As such, you can observe the state of the
background operation and optionally cancel it. Service is a reusable
Worker, meaning that it can be reset and restarted. Due to this, a
Service can be constructed declaratively and restarted on demand.
I am trying to determine the "approved" or best practices approach while in a Java EE environment for doing the following: A client is on a web page and clicks a button. This starts a thread for monitoring a process, i.e. database activity, network, etc. This process will continue to run until the user clicks a button that tells the process to end. Other clients, and/or the same client then clicks a button to listen to the status being sent from that process which will continue to listen until the user clicks a button to stop listening.
I have already done the above by using a WebSocket to communicate with a servlet which gets an injected a singleton EJB that extends WebSocketApplication. But, this EJB is spawning the process thread to do the monitoring. Although it works and should continue to work since it is a singleton, it is not the "approved" way of doing it.
Some suggestions I have reviewed discuss using JMS to spawn the thread, but, unless I am misunderstanding something, this doesn't solve anything since a Message Driven Bean isn't supposed to spawn a thread either. So, what is the approved/best practices method of doing this? How does one start and stop a background process in a Java EE environment? Again, the requirements are, only one process can be spawned, it must communicate to all WebSockets that register with the servlet, it must be able to die when told to (although that doesn't mean the server closes the sockets, since it could be started back up and would still communicate to all the previously registered clients).
Thanks.
this EJB is spawning the process thread
EJBs are not permitted to start threads. Quoth the standard:
The enterprise bean must not attempt to manage threads. The enterprise bean must not attempt
to start, stop, suspend, or resume a thread, or to change a thread’s priority or name. The enter-
prise bean must not attempt to manage thread groups.
These functions are reserved for the EJB container. Allowing the enterprise bean to manage threads
would decrease the container’s ability to properly manage the runtime environment.
This is by design; the specification states the following
The Enterprise JavaBeans architecture will make it easy to write applications: application
developers will not have to understand low-level transaction and state management details,
multi-threading, connection pooling, or other complex low-level APIs.
Have you considered using a stateful session bean? Clicking on the button causes the bean to enter the "started" state. Click on the second button causes the bean to enter the "stopped" state.
To create threads in an enterprise environment, you should use either ManagedThreadFactory or ManagedExecutorService.
Please see here
The answer is an asynchronous EJB 3.1 bean. Thanks for the reply.
As of Java EE 7 you can use the ManagedExecutorService to give your EJBs access to a managed thread pool.
i have a webapp written with spring 3 and struts 2 that is hosted on a glassfish server. In this app i have two webservices that need to do some background work without delaying the accessed method response.
So, now i use a spring bean that uses an instance of org.springframework.core.task.TaskExecutor and from there i run my new thread.
Is this the correct/best practice approach in context of using this app on glassfish? or should find another method of doing this ?
It's discouraged to create your own threads because the app server is meant to be in charge. See the answers to Why is spawning threads in Java EE container discouraged?
However in practice, especially if it's the only application on there, you might be OK, especially if you use a fixed thread pool. Be sure all the threads are gone when you undeploy the app. (I expect Spring classes will handle disposal on undeploy / shutdown correctly, if you declare them within the Spring container).
I have a traditional 3-tier application with spring. One of my repositories needs > 3 minutes for initialization so I thought about some multi-threaded approach in order to speed up the whole process - I think most service and controllers in my dependency tree can already be started so only a few must wait for the last repository to come up.
Is there any best practice approach?
Use Spring's Executor abstraction. And if you are within a app server then I suggest you use application server's work-manager (spring supports it). For e.g. WebSphere app server and Weblogic both support registering the workmanagers in JNDI. You can then pass the jndi name to spring. Task Executors