ScheduledExecutorService - program not ending after one-shot action - java

I have a scheduled task in my program that closes a frame after a given period of time. However, after the task has been executed, the program keeps running as if the ScheduledExecutorService was still running on a different thread.
This is the relevant part of my code:
int delay = 1000;
ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
ex.schedule(() -> {
System.out.println("executed");
getWindow().closeWindow();
// ex.shutdown();
}, delay, TimeUnit.MILLISECONDS);
Here the task is executed after a 1 second delay, "executed" is printed once, the frame closes, and the program keeps running even after this code. If I uncomment the ex.shutdownNow();, the program successfully ends as intended. However, I cannot figure out why this is happening. I also failed to find anything from the rest of the Internet.
MCVE:
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
int delay = 1000;
ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
ex.schedule(() -> {
System.out.println("executed");
// ex.shutdown();
}, delay, TimeUnit.MILLISECONDS);
}
}
The lambdas might've given it away, but this is indeed Java 8.
Why is the program not stopping after the task has been executed?

The ScheduledExecutorService thread pool returned by Executors#newSingleThreadScheduledExecutor() uses non daemon threads. Until you shut down the thread pool, these are still alive awaiting tasks. A JVM does not end while non-daemon threads are alive.
You can use the overloaded Executors#newSingleThreadScheduledExecutor(ThreadFactory) and provide your own ThreadFactory implementation which creates daemon threads. Note that this risks the case where your task may not even run because the JVM would exit before the task's scheduled time.
Do as you've discovered and shut it down. Note that you should shut always it down somewhere safe, where the operation can't fail.

The Java Virtual Machine runs until all threads that are not daemon threads have died. And Executors.defaultThreadFactory() creates each new thread as a non-daemon thread. However, there is an overload of Executors.newSingleThreadScheduledExecutor(); which takes a ThreadFactory as a parameter, if you care to venture in that direction.
public static void main(String[] args) {
int delay = 1000;
class DaemonFactory implements ThreadFactory
{
#Override
public Thread newThread(Runnable r)
{
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
}
ThreadFactory tf = new DaemonFactory();
ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor(tf);
ex.schedule(() -> {
System.out.println("executed");
}, delay, TimeUnit.MILLISECONDS);
}

I would approach this entirely differently. You state:
I have a scheduled task in my program that closes a frame after a given period of time.
Why not instead use a Swing Timer for this as this was built to work well with the Swing event thread?
new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
((Timer) e.getSource()).stop();
someWindow.dispose();
}
}).start();

You can call shutdown from ScheduledExecutorService as it will wait for thread execution and then finalize thread pool. As you can see in Javadoc: "Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will
be accepted. Invocation has no additional effect if already shut down."
Example:
...
scheduledExecutorService.schedule(runnable, delay, TimeUnit.MILLISECONDS);
scheduledExecutorService.shutdown();
...

I am starting scheduler from onCreate() and stopping it in onDestroy() approach to stop the scheduler service.
public MyActivity extends Activity
{
ScheduledExecutorService scheduledExecutorService;
ScheduledFuture<?> scheduledFuture;
private int apiThreshold = 10;//seconds
onCreate()
{
startScheduler();
}
onDestroy()
{
if (scheduledFuture != null)
{
stopScheduler();
}
shutDownService();
super.onDestroy();
}
public void startScheduler() {
Debug.e(TAG, "inside start scheduler");
scheduledExecutorService = Executors.newScheduledThreadPool(1);
scheduledFuture = scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
// call method to do your task/perform your repeated task
}
}, 4, apiThreshold, TimeUnit.SECONDS);
}
public void shutDownService()
{
if (scheduledExecutorService != null) {
Log.e(“test,"in shutDown service close if not null");
scheduledExecutorService.shutdownNow(); // shutdown will allow the final iteration to finish
// executing where shutdownNow() will kill it immediately
Log.e(“test,"is service shutdown(true/false)=="+scheduledExecutorService.isShutdown());
}
}
}

Related

Make other threads wait until ScheduledExecutorService completes all tasks

The main goal is to run a method using ScheduledExecutorService and wait until all its tasks complete before resuming the main thread.
I've created a utility method in custom Scheduler class that accepts any Runnable:
public void scheduleFunction(Runnable function) {
final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
final ScheduledFuture<?> producerHandle = scheduler.scheduleAtFixedRate(function, initialDelay, interval, MILLISECONDS);
scheduler.schedule(() -> { producerHandle.cancel(true); }, timeout, MILLISECONDS);
}
And use it like this in other class when I need execute its method in scheduled mode:
public void sendToKafka() {
Scheduler.scheduleFunction(this::produce);
}
This work fine, except one thing.
When the main thread reaches sendToKafka() it calls Scheduler to schedule a function. Dut the main thread keeps running, at the same time the Scheduled function starts to work.
Actual result:
two threads running at the same time
Expected result:
when scheduler thread starts the main thread stops and waits until scheduler completes execution
How can I achieve this?
Since you are creating and abandoning a ScheduledExecutorService in this method, you should call shutdown() to support timely release of the resources. If you do that, you can call awaitTermination to wait for the completion of all pending jobs.
public void scheduleFunction(Runnable function) {
final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
final ScheduledFuture<?> producerHandle
= scheduler.scheduleAtFixedRate(function, initialDelay, interval, MILLISECONDS);
scheduler.schedule(() -> {
producerHandle.cancel(true);
scheduler.shutdown();
}, timeout, MILLISECONDS);
try {
scheduler.awaitTermination(Long.MAX_VALUE, MILLISECONDS);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
Note that when you don’t need interruption, you can simply use
public void scheduleFunction(Runnable function) {
final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(function, initialDelay, interval, MILLISECONDS);
scheduler.schedule(() -> scheduler.shutdown(), timeout, MILLISECONDS);
try {
scheduler.awaitTermination(Long.MAX_VALUE, MILLISECONDS);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
as shutting down the ScheduledExecutorService implies stopping to reschedule the job; only if there’s an ongoing execution it will be completed and awaitTermination will wait for it.

Creating a thread that will execute after delay

How would I create a thread that will execute after a delay of s seconds?
I would like other processes to run while the thread is waiting.
For example, I would like to create the thread, then print out several other strings, then after s seconds, the thread will run.
What I don't need is the whole program to wait for s seconds, then everything happens. I need processes to run while the delay is ticking.
Thanks!
~Java preferred
Use a ScheduledExecutorService. See the example below.
System.out.println("some stuff");
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
final Runnable task = new Runnable() {
#Override
public void run() {
System.out.println("do something");
}
};
Future<?> futureHandle = scheduler.scheduleWithFixedDelay(task, 10, 10, TimeUnit.SECONDS);
System.out.println("some other stuff");
The task is scheduled with a fixed delay of 10 seconds, so you'll get output for the print statements not in the Runnable followed by the one in the Runnable every 10 seconds.
The output in this example is
some stuff
some other stuff
do something
do something
...
with the "do something" lines occurring at 10 sec. intervals after an initial 10 sec. delay.
To stop it, you can create a "stop" task to put some kind of logic in, and register that.
final Runnable stopTask = new Runnable() {
#Override
public void run() {
futureHandle.cancel(true); // true: interrupt if necessary
}
};
long delay = // some number, how long to wait before invoking the stop task
scheduler.schedule(stopTask, delay, TimeUnit.SECONDS).get(); // wait if necessary and get the future result
scheduler.shutdown(); // shutdown on completion
EDIT
If you just need the task to run once, as pointed out in the comments, consider a TimerTask:
final Timer timer = new Timer();
final TimerTask task = new TimerTask() {
#Override
public void run() {
System.out.println("timer task");
timer.cancel(); // stop timer after execution
}
};
timer.schedule(task, 1000); // schedule task with delay of 1000ms
I would suggest you to take look into quartz scheduler. This is very powerful and does almost similar tasks like unix cron in java environment.
There are bunch of tutorials online for quartz that you can always look into.
Here is one working example with Thread.sleep():
public class DelayThread implements Runnable {
private final int DELAY;
public DelayThread(int delay) {
this.DELAY = delay;
}
#Override
public void run() {
try {
Thread.sleep(DELAY);
System.out.println("task executed");
} catch (InterruptedException ex) {
System.out.println("interrupted");
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new DelayThread(2000));
thread1.start();
Thread.sleep(500);
Thread thread2 = new Thread(new DelayThread(2000));
thread2.start();
System.out.println("All threads are started");
}
}

How to end a thread in executor service if thread takes too long?

Sample executor service
static class MyRunnable implements Runnable {
private String serverName;
public MyRunnable(String serverName) {
super();
this.serverName = serverName;
}
#Override
public void run() {
...
conn = new ch.ethz.ssh2.Connection(serverName);
conn.connect();
boolean isAuthenticated = conn.authenticateWithPassword(user, pass);
logger.info("Connecting to " + server);
if (isAuthenticated == false) {
logger.info(server + " Please check credentials");
}
sess = conn.openSession();
...
}
}
public static void main(String[] args) {
List<String> serverList = ...;
ExecutorService executor = Executors.newFixedThreadPool(20);
for (String serverName : serverList) {
MyRunnable r = new MyRunnable(serverName);
executor.execute(r);
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.HOURS);
}
Right here is a sample code of my executor service. But with this logic when I meet a server that fails to connect or takes too long to connect it creates a a hang time within my application. I want to end/kill the thread if it takes longer than x amount of time to connect. How can I terminate the thread task if it does not connect to server within 2 seconds.
Attempt
ThreadPoolExecutor executor = new ThreadPoolExecutor(
10, 25, 500, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(1));
I added the following code but apparently it does not end the thread if it takes longer than 2000 milliseconds.
Attempt 2
Future<?> future = executor.submit( new task));
try {
future.get(2000, TimeUnit.MILLISECONDS); // This waits timeout seconds; returns null
}
catch(TimeoutException e) {
future.cancel(true);
// System.out.println(server + "name");
}
How can I terminate the thread task if it does not connect to server within 2 seconds.
This is difficult thing to do typically because even if you interrupt the thread (like the other answers mention) there's no guarantee that the thread will stop. Interrupt just sets a flag on the thread and it's up to the code to detect the status and stop. This means that a ton of threads may be in the background waiting for the connects.
In your case however you are using the ch.ethz.ssh2.Connection.connect() method. Turns out there is a connect method that takes a timeout. I think you want the following:
// try to connect for 2 seconds
conn.connect(null, 2000, 0);
To quote from the connect method javadocs:
In case of a timeout (either connectTimeout or kexTimeout) a SocketTimeoutException is thrown.
You have to do awaitTermination() first, then check the return value, and then do shutdownNow(). shutdown() does not guarantee instant stoppage of the service, it just stops taking new jobs, and waits for all jobs to complete in order. shutdownNow() on the other hand, stops taking new jobs, actively attempts to stop all running tasks, and does not start any new one, returning a list of all waiting-to-execute jobs.
From JavaDocs :
The following method shuts down an ExecutorService in two phases,
first by calling shutdown to reject incoming tasks, and then calling
shutdownNow, if necessary, to cancel any lingering tasks:
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
You can always call future.get(timeout...)
It will return timeout exception if it did not finish yet... then you can call future.cancel().
As long as you deal with threads in Java the only safe way to stop the thread is to interrupt it. You can call shutdown() first and then wait. This method doesn't interrupt threads.
If it doesn't help then you call shutdownNow() which tries to cancel tasks by setting interrupted flag of each thread to true. In that case if threads are blocked/waiting then InterruptedException will be thrown. If you check interrupted flag somewhere inside your tasks then you are good too.
But if you have no other choice but to stop threads you still can do it. One possible solution of getting access to workers is to trace all created threads inside ThreadPoolExecutor with help of custom thread factory.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class TestThreadPoolEx {
static class CustomThreadFactory implements ThreadFactory {
private List<Thread> threads = new ArrayList<>();
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
threads.add(t);
return t;
}
public List<Thread> getThreads() {
return threads;
}
public void stopThreads() {
for(Thread t : threads) {
if(t.isAlive()) {
try {
t.stop();
} catch (Exception e) {
//NOP
}
}
}
}
}
public static void main(String[] args) throws InterruptedException {
CustomThreadFactory factory = new CustomThreadFactory();
ExecutorService ex = Executors.newFixedThreadPool(1, factory);
ex.submit(() -> {
while(true);
});
ex.shutdown();
ex.awaitTermination(5, TimeUnit.SECONDS);
ex.shutdownNow();
ex.awaitTermination(5, TimeUnit.SECONDS);
factory.stopThreads();
}
}
This is sure unsafe but should fit your requirements. In this case it's able to stop while(true) loop. Cancelling tasks won't be able to do that.

Using Executor & Runnable together to kill threads after some time

I happened to come across this article for killing a thread after some time using the Executor service : Killing thread after some specified time limit in Java
This is the code mentioned in the article :
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.invokeAll(Arrays.asList(new Task()), 10, TimeUnit.MINUTES); // Timeout of 10 minutes.
executor.shutdown();
Now that I have a runnable thread to be executed in my program .How do I kill this thread after some time using the above mentioned code?
Here's a part of my code which I have used for creating threads :
public static List<Thread> thread_starter(List<Thread> threads,String filename)
{ String text=read_from_temp(filename);
Runnable task = new MyRunnable(text);
Thread worker = new Thread(task);
worker.start();
// Remember the thread for later usage
threads.add(worker);
return threads;
}
public class MyRunnable implements Runnable {
MyRunnable(String text)
{
this.text=text;
}
#Override
public void run() {
/* other computation*/
}
I create multiple threads by calling thread_started() function .
Can anyone please help me on combining Executor Service with it . I tried a lot but couldn't find any way out !
In java, you can NOT kill a running thread directly. If you want to kill your running thread, you need a running flag in your task, check it in thread task, and set it outside. Eg:
MyRunnable task = ....;
......
task.running = false; //stop one task
public class MyRunnable implements Runnable {
public boolean running = true;
public void run() {
while(running){
.....
}
}
What you mentioned 'ExecutorService' is single thread 'ExecutorService', it would exec tasks one by one, what it do for timeout is just waiting a task completed and calculate/compare each task's time with timeout. You can find it in java's source code 'AbstractExecutorService.java'.

Shutdown hook is not killing executor

I have the following code:
public class Driver {
private ExecutorService executor = Executors.newCachedThreadPool();
public static void main(String[] args) {
Driver d = new Driver();
d.run();
}
private void run() {
final Timer timer = new Timer();
final TimerTask task = new TimerTask() {
#Override
public void run() {
System.out.println("Task is running!");
}
};
Runnable worker = new Runnable() {
#Override
public void run() {
timer.scheduleAtFixedRate(task, new Date(), 5 * 1000);
}
};
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
System.out.println("Shutdown hook is being invoked!");
try {
if(executor.awaitTermination(20, TimeUnit.SECONDS))
System.out.println("All workers shutdown properly.");
else {
System.out.println(String.format("Maximum time limit of %s reached " +
"when trying to shut down workers. Forcing shutdown.", 20));
executor.shutdownNow();
}
} catch (InterruptedException interrupt) {
System.out.println("Shutdown hook interrupted by exception: " +
interrupt.getMessage());
}
System.out.println("Shutdown hook is finished!");
}
});
executor.submit(worker);
System.out.println("Initializing shutdown...");
}
}
When this runs I get the following console output:
Initializing shutdown...
Task is running!
Task is running!
Task is running!
Task is running!
Task is running!
Task is running!
Task is running!
... (this keeps going non-stop)
When I run this, the application never terminates. Instead, every 5 seconds, I see a new println of "Task is running!". I would have expected the main thread to reach the end of the main method, print "Initializing shutdown...", invoked the added shutdown hook, killed the executor, and finally print out "Shutdown hook is finished!".
Instead, "Task is running" just keeps getting printed and the program never terminates. What's going on here?
I am no expert but AFAIK you must have all non-Daemon threads terminated in order for the shutdown hook to “kick in”.
In the original example you have 3 non-Daemon:
The thread of “Main” – this is the only non-Daemon you want here..
The thread that runs the “TimerTask” – it is created by the “Timer” and you covered it by fixing to Timer(true)
The thread that runs the “worker” – it is created by the “executor” and in order for the “executor” to create Daemon threads you should create a ThreadFactory. (at least this is the way I know; there might be other ways...)
So I think what you should do is to create a ThreadFactory and use it when initializing the “executor”.
Create a class that will be the ThreadFactory:
private class WorkerThreadFactory implements ThreadFactory {
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "Worker");
t.setDaemon(true);
return t;
}
}
-- the important line is the setDaemon of course :)
Pass an instance of it as a parameter to the newCachedThreadPool method:
private ExecutorService executor = Executors.newCachedThreadPool(new WorkerThreadFactory());
Applying these 2 changes did the trick for me and I got to:
Maximum time limit of 20 reached when trying to shut down workers. Forcing shutdown.
Shutdown hook is finished!
Hope it helps,
Izik
golan2#hotmail.com
It is not shutting down because Timer() creates and starts a non-daemon thread ... which is then never stopped.
There are two things that can cause the JVM to shutdown of its own accord:
A call to System.exit() (or Runtime.halt())
The termination of the last remaining non-daemon thread.
Since you have created a second non-daemon thread (in addition to the thread that is running main()) the second condition won't be met.

Categories

Resources