Toggle ScheduledExecutorService so its not always running - java

I'm currently working on a discord bot just to mess around with, but have used SES in the past for other things, but I always struggle to disable/enable the SES, calling ses.shutdown(); does not work and the runnable continues, and if I did shutdown im not sure how to restart it.
Here is my current code...
private final ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
protected void startRainbow(Role rle) {
roleRainbow[] colors = roleRainbow.values();
HashMap<String, Integer> map = new HashMap<>();
map.put("loop", 0);
Runnable r = () -> {
if(map.get("loop") >= colors.length) {
map.put("loop", 0);
}
rle.getManager().setColor(Color.decode(colors[map.get("loop")].toString())).queue();
System.out.println("color is: " + colors[map.get("loop")].toString());
System.out.println("color from role: " + rle.getColor());
map.put("loop", map.get("loop") + 1);
};
ses.scheduleAtFixedRate(r, 1L, 1, TimeUnit.SECONDS);
}

There are two angles to this problem:
Interrupting a currently-running thread.
Graceful shut down of a scheduled executor service.
The first has been addressed many many times on Stack Overflow already. In brief: You must signal a thread that you want it to interrupt itself. That thread's task must be coded is such a way to look for the interruption signal.
For the second, there are two steps involved:
You first tell the scheduled executor service that you want to stop any further executions of future-scheduled tasks. We do this with a call to shutdown. This call does not interrupt any currently existing task (see above paragraph).
Alternatively, you may call shutdownNow. This call may signal the running task to interrupt, but no guarantees. The behavior is implementation-defined.
After requesting the service to stop further scheduling, you can watch to see if the service does indeed stop after a reasonable amount of time has passed. We do this with a call to awaitTermination.
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor() ;
ses.scheduleAtFixedRate( task , initialDelay , period , timeUnit ) ;
…
ses.shutdown() ;
boolean terminated = false ;
try { terminated = ses.awaitTermination( 1 , TimeUnit.MINUTES ); } catch ( InterruptedException e ) { e.printStackTrace(); }
if( ! terminated ) { … Houston, we have a problem. … }
The call to shutdown (and shutdownNow) does not block; it does not wait for anything to happen, and does not wait for tasks to end.
The call to awaitTermination does block until either:
Scheduled executor service finishes its last running task, and ends.
The specified time-out elapses.
Test for the boolean returned by the awaitTermination call. To quote the Javadoc:
true if this executor terminated and false if the timeout elapsed before termination
You asked:
if I did shutdown im not sure how to restart it.
Once shutdown, the scheduled executor service is done. To schedule tasks for execution, you must instantiate a new scheduled executor service.
Be aware that a scheduled executor service with no tasks to execute takes very little memory or CPU. So no need to shutdown if you might later need the service.
However, be sure to always shutdown your executor services before your app ends. Otherwise the backing thread pool(s) may continue running indefinitely, like a zombie 🧟‍♂️.

Related

How do I do a task after waiting 10 seconds in Java?

It's the first time I use Java for a project and I need to do this:
send a CoAP POST request to turn on an actuator
wait 10 seconds
send a CoAP POST request to turn off the actuator.
I'm using this code inside the method I wrote that has to automatically turn on/off the actuator:
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run (){
Request postRequest2 = new Request(CoAP.Code.POST);
postRequest2.setURI(String.format("%s%s", COAP_ENDPOINT1, targetStatusActuatorUri));
postRequest2.setConfirmable(true);
}
},
10000
);
But it throws an error Unreachable statement and I don't understand why.
As commented, you need to supply more debugging details.
ScheduledExecutorService
More generally, I can say that Timer and TimerTask classes were years ago supplanted by the Executors framework. Their Javadoc so notes.
A ScheduledExecutorService allows you to specify a delay before executing your task. Establish the service, and keep it around for later use.
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor() ;
Define your task as a Runnable (or Callable).
Runnable task = () -> {
turnOffActuator() ;
};
In your business logic, turn on the actuator, then assign the turning-off task to the executor while scheduling with a delay.
turnOnActuator() ;
ses.schedule( task , 10 , TimeUnit.SECONDS ) ;
Be sure to eventually shut down your executor service before your app ends/exits. Otherwise the pool of threads backing your executor service may continue running indefinitely, like a zombie 🧟‍♂️.
All of this has been covered many times already on Stack Overflow. Search to learn more.

How to cleanly execute tasks with async timeout in Java 8

I have a single threaded executor which reads emaling jobs from a blocking queue as I have to send emails sequentially. Sometimes the java mail sender's sendMail() call hangs up. Since I have just 1 thread sending emails, I don't want to freeze this indefinitely when mail server call hangs.
So, effectively I want to run the emailing tasks with a defined timeout after which it should be cancelled.
The way I have done this is with Java 8 Future class. So I submit the task to my single threaded executor, get the future object in return and then schedule future.cancel() in a separate scheduledExecutor. With the scheduledExecutor, my main thread which is dequeing the emailing jobs from the blocking queue remains async.
But this approach has a problem. Let's say there are 5 objects to be emailed sitting in the blocking queue. And let's assume I have a timeout of 5 secs after which future.cancel() would be called. My async dequeuing thread loops through quickly and puts all 5 objects into the single threaded executor's queue. And when my single thread picks the first job and calls JavaMail's->sendMail(), the call hangs. After 5 secs, the future.cancel() would be called on this task. But my other 4 jobs were also in the executor's queue for the last 5 secs, so their future.cancel() would also be called even before they were processed by the single thread!
Here is my existing implementation
// process sequentially using single 'EmailMain'thread.
Future future = singleThreadExecutor.submit( () -> {
try {
mailService.sendEmail( tradeConfirmationInputFields, tradeConfirmFile );
} catch ( MessagingException | IOException e ) {
log.error( "Found error", e );
return;
}
} );
// timeout the single 'EmailMain' thread if not completed within allowed time.
taskTimeoutScheduledExecutor.schedule( () -> {
future.cancel( true );
}, 5000L, TimeUnit.MILLISECONDS );
} catch ( InterruptedException e ) {
log.error( "Error while emailing tradeConfirmation", e );
}
I want each of emailing jobs to to be processed through the'EmailMain' single thread in sequence and the timer for their timeout to start when the single threads starts processing them and NOT when the jobs are added to the singleThreadedExecutor's queue. Is there any clean solution in Java 8? I know in Java 9, there is some simple option like the below (taken from
https://www.deadcoderising.com/java-9-handle-timeouts-asynchronously-using-completablefutures-ortimeout-and-completeontimeout/
):
CompletableFuture.supplyAsync(this::getArticles)
.orTimeout(1, TimeUnit.MINUTES);

threads created by ThreadPoolExecutor keeps running after shutdown

I am trying to apply the priciple of Multithread producer/consumer of some datas using two threadPoolExecutors, i noticed that everything works fine but the program refuse to shut down and some threads are still running after shutting down the 2 threadPools:
In main class:
ExecutorService executor = new ThreadPoolExecutor(10, 10, 40, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(edmsIds.size()));
ExecutorService consumerExecutor = new ThreadPoolExecutor(10, 10, 0L, TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(edmsIds.size()));for(
String edmsID:edmsIds)
{
Runnable worker = new BatchWorkerThread(resumeFile, stratrKeysToUpdate, xslFiles, errorThrown, edmsID,
consumerExecutor, edmsIds.size(), executor);
executor.execute(worker);
}
In producer Class:
while (edmsNumber > 0) {
Runnable consumer = new ConsumerThread(brokerWorker);
consumExecutor.execute(consumer);//decreasing the edmsNumber
}
if (edmsNumber < 1) {
prodExecutor.shutdownNow();
consumExecutor.shutdownNow();
}
See the doc:
There are no guarantees beyond best-effort attempts to stop processing
actively executing tasks. For example, typical implementations will
cancel via Thread.interrupt(), so any task that fails to respond to
interrupts may never terminate.
If the running task is not interruptable(does not respond to interrupt singal), it will continue execute.
Actually i wanted to post the cause of the problem and the solution :
Cause
i was trying to shutdown the excutor while it is not terminated yet.
Solution
shut it down only after its termination using a simple code.
For example :
prodExecutor.shutdownNow();
while (!prodExecutor.isTerminated()) {}
Another solution is to use ExecutorCompletionService if you want to take tasks as they complete you need an ExecutorCompletionService. This acts as a BlockingQueue that will allow you to poll for tasks as and when they finish.

How to be sure threads are cleaned up

I have a method producer.postMessage(message) which sends a message to some queue. If for some reason the message could not be sent in a period of time I want this task to be canceled. I came up with the implementation below. My question is if there is an interrupt can I be sure the Future task/ executor service are all shutdown and if not what changes need to be made to make this working without any threads not being terminated.
Thanks a lot
public void postMessage(final Object object)
{
LOG.debug("postMessage object " + object.getClass().getSimpleName());
Message message = new Message("task", 10, object);
try
{
ExecutorService ex = Executors.newSingleThreadExecutor();
Future<?> f = ex.submit(new Runnable()
{
public void run()
{
producer.postMessage(message);
LOG.debug("Finished sending message for " + object.getClass().getSimpleName());
}
});
f.get(5, TimeUnit.SECONDS);
ex.shutdown();
}
catch (InterruptedException | ExecutionException | TimeoutException e)
{
LOG.error("Could not deliver message to the queue, Check AMQ is running");
}
}
The shutdown() method on an Executor will stop it from accepting new tasks, but attempts to complete the running tasks. You should use method shutdownNow() to have the Executor request that currently running tasks are stopped.
This may not be necessary however, if you use method cancel(boolean mayInterruptIfRunning) on the Future object. f.get(5, TimeUnit.SECONDS) will wait at most 5 seconds for completion of the tasks before returning. Since you submit a Runnable rather than a Callable, the return will always be null; Runnables can't return a result, while Callables can. What you can do is call isDone() on the Future after the get with a 5 second timeout, and if it returns false, it means the tasks has not completed. In that case you can then call cancel(true) on the Future to attempt to cancel the task. The true argument indicates that you'll allow the Future to interrupt the thread if it is running. You may want to catch InterruptedExceptions in your Runnable and log them. Note however that not every call may respond to interrupt requests (for example, some I/O operations may not, while a lot of Java NIO stuff does).
Calling the shutdown on the executor may no longer be necessary, since it's only used for a single task and should have no other waiting or running tasks, but it's probably still good form.
So your code would become:
f.get(5, TimeUnit.SECONDS);
if (!f.isDone())
f.cancel(true);
ex.shutdown();

Graceful shutdown of threads and executor

The following piece of code tries to accompolish this.
The code loops forever and checks if there are any pending requests to be processed. If there is any, it creates a new thread to process the request and submits it to the executor. Once all the threads are done,it sleeps for 60 seconds and again checks for pending requests.
public static void main(String a[]){
//variables init code omitted
ExecutorService service = Executors.newFixedThreadPool(15);
ExecutorCompletionService<Long> comp = new ExecutorCompletionService<Long>(service);
while(true){
List<AppRequest> pending = service.findPendingRequests();
int noPending = pending.size();
if (noPending > 0) {
for (AppRequest req : pending) {
Callable<Long> worker = new RequestThread(something, req);
comp.submit(worker);
}
}
for (int i = 0; i < noPending; i++) {
try {
Future<Long> f = comp.take();
long name;
try {
name = f.get();
LOGGER.debug(name + " got completed");
} catch (ExecutionException e) {
LOGGER.error(e.toString());
}
} catch (InterruptedException e) {
LOGGER.error(e.toString());
}
}
TimeUnit.SECONDS.sleep(60);
}
}
My question is most of the processing done by these threads deal with database. And this program will run on a windows machine. What happens to these threads when someone tries to shutdown or logoff the machine.? How to gracefully shutdown the running threads and also the executor.?
A typical orderly shutdown of an ExecutorService might look something like this:
final ExecutorService executor;
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
executor.shutdown();
if (!executor.awaitTermination(SHUTDOWN_TIME)) { //optional *
Logger.log("Executor did not terminate in the specified time."); //optional *
List<Runnable> droppedTasks = executor.shutdownNow(); //optional **
Logger.log("Executor was abruptly shut down. " + droppedTasks.size() + " tasks will not be executed."); //optional **
}
}
});
*You can log that the executor still had tasks to process after waiting the time you were willing to wait.
**You can attempt to force the executor's worker Threads to abandon their current tasks and ensure they don't start any of the remaining ones.
Note that the solution above will work when a user issues an interrupt to your java process or when your ExecutorService only contains daemon threads. If, instead, the ExecutorService contains non-daemon threads that haven't completed, the JVM won't try to shutdown, and therefore the shutdown hooks won't be invoked.
If attempting to shutdown a process as part of a discrete application lifecycle (not a service) then shutdown code should not be placed inside a shutdown hook but at the appropriate location where the program is designed to terminate.
The book "Java Concurrency in Practice" states:
7.4. JVM Shutdown
The JVM can shut down in either an
orderly or abrupt manner. An orderly
shutdown is initiated when the last
"normal" (nondaemon) thread
terminates, someone calls System.exit,
or by other platform-specific means
(such as sending a SIGINT or hitting
Ctrl-C). [...]
7.4.1. Shutdown Hooks
In an orderly shutdown, the JVM first
starts all registered shutdown hooks.
Shutdown hooks are unstarted threads
that are registered with
Runtime.addShutdownHook. The JVM makes
no guarantees on the order in which
shutdown hooks are started. If any
application threads (daemon or
nondaemon) are still running at
shutdown time, they continue to run
concurrently with the shutdown
process. When all shutdown hooks have
completed, the JVM may choose to run
finalizers if runFinalizersOnExit is
true, and then halts. The JVM makes no
attempt to stop or interrupt any
application threads that are still
running at shutdown time; they are
abruptly terminated when the JVM
eventually halts. If the shutdown
hooks or finalizers don't complete,
then the orderly shutdown process
"hangs" and the JVM must be shut down
abruptly. [...]
The important bits are,
"The JVM makes no attempt to stop or interrupt any application threads that are still running at shutdown time; they are abruptly terminated when the JVM eventually halts." so I suppose the connection to the DB will abruptly terminate, if no shutdown hooks are there to do a graceful clean up (if you are using frameworks, they usually do provide such shutdown hooks). In my experience, session to the DB can remain until it is timed out by the DB, etc. when the app. is terminated without such hooks.
Since adding a shutdown hook to explicitly call shutdown() didn't work for me, I found an easy solution in Google's Guava:
com.google.common.util.concurrent.MoreExecutors.getExitingExecutorService.
You can either call shutdown() on the ExecutorService:
Initiates an orderly shutdown in which
previously submitted tasks are
executed, but no new tasks will be
accepted.
or you can call shutdownNow():
Attempts to stop all actively
executing tasks, halts the processing
of waiting tasks, and returns a list
of the tasks that were awaiting
execution.
There are no guarantees beyond
best-effort attempts to stop
processing actively executing tasks.
For example, typical implementations
will cancel via Thread.interrupt(), so
any task that fails to respond to
interrupts may never terminate.
Which one you call depends how badly you want it to stop....
I had similar issue, i use to get error like
o.a.c.loader.WebappClassLoaderBase :: The web application [ROOT] appears to have started a thread named [pool-2-thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
Bellow code fixed it
private ThreadPoolExecutor executorPool;
#PostConstruct
public void init() {
log.debug("Initializing ThreadPoolExecutor");
executorPool = new ThreadPoolExecutor(1, 3, 1, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1));
}
#PreDestroy
public void destroy() {
log.debug("Shuting down ThreadPoolExecutor");
executorPool.shutdown();
}

Categories

Resources