Set a timeout in Executor.execute() - java

I need to execute tasks sequentially:
Executor executor = Executors.newSingleThreadExecutor();
public void push(Runnable task) {
executor.execute(task);
}
Sometimes a task never ends. I would like to set a timeout to prevent it from blocking the next.
Edit: I need a "fire and forget" design as I can't block the caller of this execution

This can be done using Future object.
ExecutorService executor = Executors.newSingleThreadExecutor();
Runnable task = new Runnable() {
#Override
public void run() {
//do your task
}
};
Future<?> future = executor.submit(task);
future.get(60, TimeUnit.SECONDS); // awaits termination

Related

Is java ExecutorService newSingleThreadExecutor performs all the tasks using only one Thread?

I know that a java thread cannot be restarted. So when I submit more than one tasks to newSingleThreadExecutor, then how does it perform all tasks using single thread?
My understanding is that newSingleThreadExecutor will use maximum one thread at a time to process any submitted tasks. I guess same for newFixedThreadPool.
If a Thread cannot be restarted then for performing n tasks, n threads should be spawned. I think newSingleThreadExecutor, newFixedThreadPool will make sure that not many threads should be spawned at a same time, like we do without using ExecutorService (where we attach each task with a thread and start separately)
Here is code example
class Task implements Runnable {
public void run() {
System.out.println("ThreadID-" + Thread.currentThread().getId());
try {
Thread.sleep(100);
}
catch (InterruptedException e) {
}
}
}
public class SingleThreadExecutorTest {
public static void main(String[] args) {
System.out.println("ThreadID-" + Thread.currentThread().getId());
ExecutorService ex = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
ex.execute(new Task());
}
}
}
The above code always prints the same ThreadID.
If I replace below line
Executors.newSingleThreadExecutor();
with
ExecutorService ex = Executors.newFixedThreadPool(2);
Then again it is able to perform all tasks using 2 Threads.
Only when I use
Executors.newCachedThreadPool();
I see different Thread IDs.
How does ExecutorService reuse a Thread?
Does it not let it reach to Dead State?
The ThreadPoolExecutor maintains some Worker threads, which work like this:
public class Demo {
public class Worker implements Runnable {
#Override
public void run() {
Runnable task = getTaskFromQueue();
while (task != null) {
task.run();
task = getTaskFromQueue(); // This might get blocked if the queue is empty, so the worker thread will not terminate
}
}
}
public static void main(String[] args) {
Worker worker = new Worker();
Thread thread = new Thread(worker);
thread.start();
}
}
When you submit a task to ThreadPoolExecutor which has a single Worker thread, the calling threads will put the task into a BlockingQueue on below condition:
the single Worker is busy
the BlockingQueue is not full
And when the Worker is free, it will retrieve new task from this BlockingQueue.

How to wait for ExecutorService to finish without shutdown?

I have some Runnables inside ExecutorService, and would like to join the threads after:
private void foo() {
//...
exec.execute(new Runnable(){
public void run() {
if (bar()) {
foo();
}
}
});
}
//exec.shutdown()
//exec.awaitTermination();
Because it calls itself inside the Runnable so I cannot just shutdown because it may prevent itself to create new tasks.
How can I wait for all threads to finish without shutdown? Is there any way to return a future so I can use Future::get().
Executor.submit(Runnable) will return a Future that according to the javadoc:
The Future's get method will return null upon successful completion.
So you can still call future.get() and have it block until the task completes.
Future<?> future = exec.submit(new Runnable(){
public void run() {
if (bar()) {
foo();
}
}
});
//blocks
future.get();

Fire and forget with java.util.concurrent

How to go about implementing a "fire and forget" behavior with java.util.concurrency? I tried:
ExecutorService executor = Executors.newSingleThreadExecutor();
public void push(Callable<Boolean> task) {
Future<Boolean> future = executor.submit(task);
future.get(timeout, timeoutUnit);
}
but the get() is blocking until completion. The push() caller is not interested in the result of the task.
Don't call get(). submit() is enough to start the Callable in a Thread. You can pass around the Future and call its get() when you are ready to get the result (if ever).
The Javadoc states
Submits a value-returning task for execution and returns a Future
representing the pending results of the task. The Future's get method
will return the task's result upon successful completion.
If you would like to immediately block waiting for a task, you can use
constructions of the form result = exec.submit(aCallable).get();
So just don't call get().
dont need the future object if you have to forget it i.e. dont care about the future of the thread. :)
ExecutorService executor = Executors.newSingleThreadExecutor();
public void push(Callable<Boolean> task) {
executor.submit(task);
}
or if you need to use future some time later than :-
ExecutorService executor = Executors.newSingleThreadExecutor();
public void push(Callable<Boolean> task) {
someCollection.add(executor.submit(task)); // use futures later
}
or just use execute from Executor and pass Runnable, if you dont intent to get the future at all.
ExecutorService executor = Executors.newSingleThreadExecutor();
public void push(Runnable task) {
executor.execute(task);
}
// execute will invoke default exceptional handler in case of exception, that can be lost in case if you dont get hold of futures in submit method.

Stop a runnable in a separate Thread

Hey there i currently have a problem with my android app. I´m starting an extra thread via
implementing the Excecutor Interface:
class Flasher implements Executor {
Thread t;
public void execute(Runnable r) {
t = new Thread(r){
};
t.start();
}
}
I start my Runnable like this:
flasherThread.execute(flashRunnable);
but how can i stop it?
Ok, this is just the very basic threading 101, but let there be another example:
Old-school threading:
class MyTask implements Runnable {
public volatile boolean doTerminate;
public void run() {
while ( ! doTerminate ) {
// do some work, like:
on();
Thread.sleep(1000);
off();
Thread.sleep(1000);
}
}
}
then
MyTask task = new MyTask();
Thread thread = new Thread( task );
thread.start();
// let task run for a while...
task.doTerminate = true;
// wait for task/thread to terminate:
thread.join();
// task and thread finished executing
Edit:
Just stumbled upon this very informative Article about how to stop threads.
Not sure that implementing Executor is a good idea. I would rather use one of the executors Java provides. They allow you to control your Runnable instance via Future interface:
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<?> future = executorService.submit(flashRunnable);
...
future.cancel(true);
Also make sure you free resources that ExecutorService is consuming by calling executorService.shutdown() when your program does not need asynchronous execution anymore.
Instead of implementing your own Executor, you should look at ExecutorService. ExecutorService has a shutdown method which:
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.
I would suggest to use the ExecutorService, along with the Furure object, which gives you control over the thread that is being created by the executor. Like the following example
ExecutorService executor = Executors.newSingleThreadExecutor();
Future future = executor.submit(runnabale);
try {
future.get(2, TimeUnit.SECONDS);
} catch (TimeoutException ex) {
Log.warn("Time out expired");
} finally {
if(!future.isDone()&&(!future.isCancelled()))
future.cancel(true);
executor.shutdownNow();
}
This code says that the runnable will be forced to terminate after 2 seconds. Of course, you can handle your Future ojbect as you wish and terminate it according to your requierements

Stop a periodic task from within the task itself running in a ScheduledExecutorService

Is there a nice way to stop the repetition of task from within the task itself when running in a ScheduledExecutorService?
Lets say, I have the following task:
Future<?> f = scheduledExecutor.scheduleAtFixedRate(new Runnable() {
int count = 0;
public void run() {
System.out.println(count++);
if (count == 10) {
// ??? cancel self
}
}
}, 1, 1, TimeUnit.SECONDS);
From outside, it is easy to cancel via f.cancel(), but how can I stop the repetition at the specified place? (Passing the Future through an AtomicReference is not safe, because there is a potential window when the scheduleAtFixedRate returns f late and the variable is set late too, and the task itself might already run, seeing a null in the reference.)
When a repeating task throws an Exception or Error, it is placed in the Future and the task is not repeated again. You can throw a RuntimeException or Error of your choice.
Instead of using an anonymous inner class you can use a named class which can then have a property for the Future object you get from the Executor when you schedule a task.
abstract class FutureRunnable implements Runnable {
private Future<?> future;
/* Getter and Setter for future */
}
When you schedule a task you can then pass the Future to the Runnable.
FutureRunnable runnable = new FutureRunnable() {
public void run() {
if (/* abort condition */)
getFuture().cancel(false);
}
};
Future<?> future = executor.scheduleAtFixedRate(runnable, ...);
runnable.setFuture(future);
Maybe you will have to make sure, that the task is not executed before the Future has been set, because otherwise you will get a NullPointerException.
It seems like bad design for the Runnable to know anything about the executor it is running in, or to throw an error if reaching 10 is not an error state is a hack.
Can you do the loop to 10 outside of the scheduling and execution? This may require using a non-scheduling executor as you'd be scheduling them manually yourself.
Here is another way, that's even Thread safe;
final Future<?>[] f = {null};
f[0]= scheduledExecutor.scheduleAtFixedRate(new Runnable() {
int count = 0;
public void run() {
System.out.println(count++);
if (count == 10) {
Future<?> future;
while(null==(future = f[0])) Thread.yield();//prevent exceptionally bad thread scheduling
future.cancel(false);
return;
//cancel self
}
}
}, 1, 1, TimeUnit.SECONDS);
Just saw this now... because I wanted to do the same thing... here is my solution, I suspect this is threadsafe.
First create a container for the Future:
public static class Cancel {
private ScheduledFuture<?> future;
public synchronized void setFuture(ScheduledFuture<?> future) {
this.future = future;
}
public synchronized void stop() {
LOG.debug("cancelling {}", future);
future.cancel(false);
}
}
And then the future code:
final Cancel controller = new Cancel();
synchronized (controller) {
ScheduledFuture<?> future = scheduler.scheduleWithFixedDelay(() -> {
if (<CONTINUE RUNNING CONDITION) {
} else {
// STOP SCHEDULABLE FUTURE
controller.stop();
}
}, startTime, timeBetweenVisbilityChecks);
controller.setFuture(future);
}
}
So notice how the stop will not be callable until the future has been created and the future has been set on the controller.
Bear in mind that the Runnable is the anomymous inner class and this will get run in a different thread altogether.

Categories

Resources