How to wait for ExecutorService to finish without shutdown? - java

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();

Related

Thread won't die and two of them keep overlapping

I need a thread that will only run once at a time, for example if it's called for the first time it will run, if it is called a second time, the first should stop completely and be allowed to die and a new one should take it's place.
I was ran a small test to see what was actually happening between each execution, the results show that the thread doesnt die but instead two threads are being executed alongside:
public class Test {
Worker worker = new Worker();
#Override
public void valid() {
try {
if (worker.running) {
worker.running = false;
worker.join();
}
} catch (InterruptedException iex) {
worker.running = false;
}
worker = new Worker();
worker.start();
}
private final class Worker extends Thread {
private volatile boolean running = true;
#Override
public void run() {
while (running) {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException iex) {
Thread.currentThread().interrupt();
}
}
}
}
}
The results are as follows:
//Upon first execution
Thread-4
Thread-4
Thread-4
Thread-4
//When I execute it again
Thread-7
Thread-4
Thread-7
Thread-4
Thread-7
Thread-4
I've tried using ExecutorService or using while(!Thread.currentThread.isInterrupted) instead of the boolean flag, and got the same results.
How can I properly stop "Thread-4" and have only one of them running?
The actual issue comes from a thread that will cycle through a list and update things on discord chat by request, what the thread does is listen to input and change as suggested by kidney I'm trying to use executor.submit() and Future
private ExecutorService executor = Executors.newSingleThreadExecutor();
private Future<Void> worker;
private void setupImageThread() {
if (!worker.isDone() && !worker.isCancelled()) {
worker.cancel(true);
}
this.worker = (Future<Void>)executor.submit(new Cycler(Listener.queue(), this.links, Cel.cMember()));
ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
Runnable timeout = () -> {
executor.shutdown();
};
ses.schedule(timeout, 100, TimeUnit.SECONDS);
}
How can I go about initializing the Future for the first time it is created?
Using single thread executor service, I would try something like this:
public class Test {
private static ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Void> worker;
public Test() {
this.worker = executor.submit(new Worker());
}
#Override
public void valid() {
if (!worker.isDone() && !worker.isCancelled()) {
worker.cancel(true); // Depends on whether you want to interrupt or not
}
this.worker = executor.submit(new Worker());
}
}
And make Worker implement Runnable.
It seems that the method valid can be called several times simultaneously. That means, every of those calls will wait to end only for one thread (Worker), whereas, every of them creates its own Worker and you lose a pointer to it, so it impossible to stop bunch of new created workers.
You should make the valid method synchronized: synchronized void valid() it will prevent creating many workers:
#Override
synchronized public void valid() {
...
}
One more thing to say. You put the while loop outside the try-catch, which is wrong: if the tread gets interrupted, the interruption doesn't kill it, because next interation gets started, so it should be like that:
#Override
public void run() {
try {
while (running) {
System.out.println(Thread.currentThread().getName());
Thread.sleep(2000);
}
catch (InterruptedException iex) {
//you don't need here Thread.currentThread().interrupt() call, because the thread has alredy been interrupted.
// The return statement here is also obsolete, I just use it as an example, but you can use empty braces.
return;
}
}
}

Java - How to tell all subthreads are done

I want to run a few tasks simultaneously so I have a code that looks like this:
for(final Task task : tasks){
(new Thread(){public void run(){
task.run(args);
}}).start();
How can I know when all of the tasks are done (the amount of tasks can vary) so that I can run something only after everything is done?
System.out.println("All tasks are finished");
A shorter version is to use a parallelStream
tasks.parallelStream().forEach(t -> t.run(args));
This will run all the tasks, using all the CPUs you have (if you have enough tasks) and wait for the all to finish.
Instead of creating Threads explicitly, submit your Runnables to an ExecutorService, then call its shutdown and awaitTermination methods:
ExecutorService executor = Executors.newFixedThreadPool(tasks.size());
for (final Task task : tasks) {
executor.submit(new Runnable() {
#Override
public void run() {
task.run(args);
}
});
}
executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLSECONDS);
You can also use a CountDownLatch to indicate if the threads are complete. See https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html
Like so:
public static class Task {
void run(String args[]) {
System.out.println("Hello");
}
}
public static void main(String[] args) {
List<Task> tasks = Arrays.asList(new Task(), new Task(), new Task());
CountDownLatch doneSignal = new CountDownLatch(tasks.size());
for(final Task task : tasks) {
(new Thread() {
public void run(){
task.run(args);
}
}).start();
doneSignal.countDown(); //counts latch down by one
}
//A
new Thread() {
public void run() {
try {
doneSignal.await(); //blocks until latch counted down to zero
System.out.println("All tasks completed");
} catch(Exception e) {
System.out.println("Warning: Thread interrupted.");
}
}
}.start();
}
Each task thread will count the latch down by one when they complete. The Thread created at //A will wait until the latch has been count down to zero. Only then, the "All tasks completed" statement will be printed. So basically the statement after doneSignal.await() will only execute after all threads have completed.
Use CyclicBarrier , example :
http://tutorials.jenkov.com/java-util-concurrent/cyclicbarrier.html
Simply add each thread to a list when you create it:
LinkedList<Thread> threads = new LinkedList<>();
And when you make a new thread:
Thread t = new Thread() {
public void run() {
task.run(args);
}
}
threads.add(t);
Then you can check each thread in your list to see if it is finished:
boolean allFinished = true;
for (Thread t : threads) {
if (t.isAlive()) {
allFinished = false;
break;
}
}
See this link for more info on checking if threads are finished:
How to know if other threads have finished?
The key point in this questions is that if you want to check on threads later, you MUST store a list (or array, etc) of them somewhere.
Another way is to use the Future interface. Doing it this way gives you some other nifty features. See this for some examples.

Cancel asynchronous calls

We need to implement a feature that allows us to cancel a future job. Given that this job is doing DB calls and we need to rollback\cleanup any updates made before cancel was fired.
This is what I have tried, but "Thread.currentThread().isInterrupted()" always return false:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
final Future future = executor.submit(new Callable() {
#Override
public Boolean call() throws Exception {
// Do Some DB calls
if (Thread.currentThread().isInterrupted()) {
// Will need to roll back
throw new InterruptedException();
}
return true;
}
});
executor.schedule(new Runnable() {
public void run() {
future.cancel(true);
}
}, 1, TimeUnit.SECONDS);
Is this the right approach to achieve our target? And how to know if the job was cancelled in order to cancel\roll back changes?
I believe that you complete the database calls before the second task gets a chance to run. When you have only a single executor it is possible that it does not schedule time for the second scheduled task before the first completes. This following snippet does get interrupted:
import java.util.*;
import java.util.concurrent.*;
public class Main {
public static void main(String[] arg) {
ScheduledExecutorService runner = Executors.newScheduledThreadPool(2);
// If this is 1 then this will never be interrupted.
final Future f = runner.submit(new Callable<Boolean>() {
public Boolean call() throws Exception {
System.out.println("Calling");
while (! Thread.currentThread().isInterrupted()) {
;
}
System.out.println("Interrupted");
return true;
}
});
runner.schedule(new Runnable() {
public void run() {
System.out.println("Interrupting");
f.cancel(true);
}
}, 1, TimeUnit.SECONDS);
}
}
First it seems the thread pool is not creating new thread for you so your cancel task will get called only after the DB task finishes. So I changed the pool size in yours example to 2 and it worked.

Set a timeout in Executor.execute()

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

How to stop a thread by another thread?

I have some struggle with threads in Java, I have three threads - thread1, thread2, and thread3. Those are doing some task when it started, I want to stop these two threads by thread1. I put thread1 for sleep(500), then I stop the both threads, but the process of two threads are still running. Do you have any idea how to do this?
How're you attempting to stop them? Thread.stop? Be warned that this method is deprecated.
Instead, look into using some sort of flag for thread 1 to communicate to thread 2 and 3 that they should stop. In fact, you could probably use interrupts.
Below, Thread.interrupt is used to implement the coordination.
final Thread subject1 = new Thread(new Runnable() {
public void run() {
while (!Thread.interrupted()) {
Thread.yield();
}
System.out.println("subject 1 stopped!");
}
});
final Thread subject2 = new Thread(new Runnable() {
public void run() {
while (!Thread.interrupted()) {
Thread.yield();
}
System.out.println("subject 2 stopped!");
}
});
final Thread coordinator = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException ex) { }
System.out.println("coordinator stopping!");
subject1.interrupt();
subject2.interrupt();
}
});
subject1.start();
subject2.start();
coordinator.start();
Alternatively, you could also use a volatile boolean (or AtomicBoolean) as means of communicating.
Atomic access provided by volatile and java.util.concurrent.atomic.* allow you to ensure mutation of the flag is seen by the subject threads.
final AtomicBoolean running = new AtomicBoolean(true);
final ExecutorService subjects = Executors.newFixedThreadPool(2);
subjects.submit(new Runnable() {
public void run() {
while (running.get()) {
Thread.yield();
}
System.out.println("subject 1 stopped!");
}
});
subjects.submit(new Runnable() {
public void run() {
while (running.get()) {
Thread.yield();
}
System.out.println("subject 2 stopped!");
}
});
final ScheduledExecutorService coordinator = Executors.newSingleThreadScheduledExecutor();
coordinator.schedule(new Runnable() {
public void run() {
System.out.println("coordinator stopping!");
running.set(false);
subjects.shutdown();
coordinator.shutdown();
}
}, 500, TimeUnit.MILLISECONDS);
Similarly, you could opt to, rather than use AtomicBoolean, use a field such as:
static volatile boolean running = true;
Better yet, if you take advantage of ExecutorServices, you can also program similar code as follows:
final ExecutorService subjects = Executors.newFixedThreadPool(2);
subjects.submit(new Runnable() {
public void run() {
while (!Thread.interrupted()) {
Thread.yield();
}
System.out.println("subject 1 stopped!");
}
});
subjects.submit(new Runnable() {
public void run() {
while (!Thread.interrupted()) {
Thread.yield();
}
System.out.println("subject 2 stopped!");
}
});
final ScheduledExecutorService coordinator = Executors.newSingleThreadScheduledExecutor();
coordinator.schedule(new Runnable() {
public void run() {
System.out.println("coordinator stopping!");
subjects.shutdownNow();
coordinator.shutdown();
}
}, 500, TimeUnit.MILLISECONDS);
This takes advantage of the fact that ThreadPoolExecutor.shutdownNow interrupts its worker threads in an attempt to signal shutdown.
Running any example, the output should be something to the effect of:
C:\dev\scrap>javac CoordinationTest.java
C:\dev\scrap>java CoordinationTest
coordinator stopping!
subject 1 stopped!
subject 2 stopped!
Note the last two lines can come in either order.
You can't stop a thread from another thread. You can only ask the thread to stop itself, and the best way to do that is to interrupt it. The interrupted thread must collaborate, though, and respond to the interruption as soon as possible by stopping its execution.
This is covered in the Java tutorial about concurrency.
You can either:
Have some boolean flag which the threads check regularly. If it is changed, then, they stop executing (note this can cause race conditions)
Another option would be to use the ExecutorService:
An Executor that provides methods to manage termination and methods
that can produce a Future for tracking progress of one or more
asynchronous tasks.

Categories

Resources