This question already has answers here:
ExecutorService, how to wait for all tasks to finish
(16 answers)
Closed 2 years ago.
I have a newbie question. I have this code:
public class Main
{
public static void main(String[] args) throws InterruptedException
{
// TODO Auto-generated method stub
IntHolder aHolder=new IntHolder();
aHolder.Number=0;
IncrementorThread A= new IncrementorThread(1, aHolder);
IncrementorThread B= new IncrementorThread(2, aHolder);
IncrementorThread C= new IncrementorThread(3, aHolder);
A.start();
B.start();
C.start();
A.join();
B.join();
C.join();
System.out.println("All threads completed...");
}
}
Which will wait for all threads to complete. If I use Executors like this:
public class Main
{
public static void main(String[] args)
{
// TODO Auto-generated method stub
IntHolder aHolder=new IntHolder();
aHolder.number=0;
IncrementalRunable A= new IncrementalRunable(1, aHolder);
IncrementalRunable B= new IncrementalRunable(2, aHolder);
IncrementalRunable C= new IncrementalRunable(3, aHolder);
ExecutorService exec = Executors.newFixedThreadPool(3);
exec.execute(A);
exec.execute(B);
exec.execute(C);
//Don't know what to do here
System.out.println("All threads completed...");
}
}
How can I suspend the main thread to wait for all the threads in the executor to finish, i.e the "All threads completed..." should be printed after the all the threads have done their work?
You shouldn't use executor like this if you want to wait for tasks to finish.
What if you don't want/can't shutdown your thread pool executor?
This is a more recommended way:
ExecutorService exec = Executors.newFixedThreadPool(3);
Collection<Future<?>> tasks = new LinkedList<Future<?>>();
Future<T> future = exec.submit(A);
tasks.add(future);
future = exec.submit(B);
tasks.add(future);
future = exec.submit(C);
tasks.add(future);
// wait for tasks completion
for (Future<?> currTask : tasks) {
try {
currTask.get();
} catch (Throwable thrown) {
Logger.error(thrown, "Error while waiting for thread completion");
}
}
executor.shutdown();
while (!executor.awaitTermination(24L, TimeUnit.HOURS)) {
System.out.println("Not yet. Still waiting for termination");
}
Use shutdown() + awaitTermination() combination.
EDIT:
Based on the comment of #Lital
List<Callable<Object>> calls = new ArrayList<Callable<Object>>();
calls.add(Executors.callable(new IncrementalRunable(1, aHolder)));
calls.add(Executors.callable(new IncrementalRunable(2, aHolder)));
calls.add(Executors.callable(new IncrementalRunable(3, aHolder)));
List<Future<Object>> futures = executor.invokeAll(calls);
NOTE:
invokeAll() will not return until all the tasks are completed (either by failing or completing successful execution).
We can use below code to join the thread.
executor.execute(new YouThread());
try{
executor.shutdown();
while (!executor.awaitTermination(24L, TimeUnit.HOURS)) {
System.out.println("Not yet. Still waiting for termination");
}
}catch(InterruptedException e){
e.printStackTrace();
}
Try working with thread pool this way.
executor.shutdown();
executor.awaitTermination(MAX_PRIORITY, TimeUnit.HOURS);
exec.shutdown();
// Wait until all threads are finish
exec.awaitTermination();
Related
This question already has answers here:
FutureTask get vs run, task never finishes
(3 answers)
Closed 9 months ago.
I try to make an API aysnchronous as:
Future<Integer> fASync(int x) {
return new FutureTask(() -> {
try {
Thread.sleep(new Random().nextInt(1, 3) * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return x * x;
});
}
..then I try to use it:
Future<Integer> asyncCall = fASync(x);
asyncCall .get();
But this never completes and call just blocks.
Is this not correct way of making your API asynchronous?
You have declared a FutureTask but haven't actually run it so a call to asyncCall.get() will block forever.
Here is your example with extra logging and adding a step to execute the task in a new ExecutorService.
static FutureTask<Integer> fASync(int x) {
System.out.println("fASync("+x+") called");
return new FutureTask<>(() -> {
System.out.println("fASync("+x+") FutureTask has started");
try {
Thread.sleep(new Random().nextInt(1, 3) * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("fASync("+x+") FutureTask has ended");
return x * x;
});
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService exec = Executors.newFixedThreadPool(1);
FutureTask<Integer> task = fASync(5);
// MUST execute the task or task.get() will block forever
exec.execute(task);
System.out.println("task.get()="+task.get());
exec.shutdown();
exec.awaitTermination(1, TimeUnit.DAYS);
System.out.println("ENDED");
}
If you enable the exec.execute(task); line it will print these messages and complete task.get(), instead of printing the first line only and no response from task.get():
fASync(5) called
fASync(5) FutureTask has started
fASync(5) FutureTask has ended
task.get()=25
ENDED
I created a thread pool, and submitted two tasks. Why does my application hang without any exceptions after print task one ,result: null???
private final static ThreadPoolExecutor executorService = new
ThreadPoolExecutor(1, 1, 1L, TimeUnit.MINUTES,
new SynchronousQueue<Runnable>(), new ThreadPoolExecutor.DiscardPolicy());
public static void main(String[] args) throws Exception {
Future taskOne = executorService.submit(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Future taskTwo = executorService.submit(() -> System.out.println("task two is working"));;
System.out.println("task one ,result: " + taskOne.get());
System.out.println("task two, result: " + taskTwo.get());
executorService.shutdown();
}
When you submit the second task, the rejection policy is triggered because the thread pool uses SynchronousQueue and maximumPoolSize is 1, while the first task has not completed. You are using DiscardPolicy, which means that the thread pool does nothing and returns you a FutureTask whose state is always NEW.
public static class DiscardPolicy implements RejectedExecutionHandler {
public DiscardPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}
So when you call taskTwo#get(), you will always be blocked. (FutureTask will always be blocked when it is in a state smaller than COMPLETING, see FutureTask#get).
You can use AbortPolicy (the default policy), so that when you execute executorService.submit(() - > submit; System.out.println("task two is working")), you immediately get a RejectedExecutionException.
Or use Future#get(timeout), in which case you get a TimeoutException if you do not get a result for a specified time.
new ThreadPoolExecutor.DiscardPolicy() silently discards the new task when it fails to submit it. here taskTwo wants to get executed, it never gets a chance to execute.
DiscardPolicy() method internally call void rejectedExecution(Runnable r, ThreadPoolExecutor executor) from RejectedExecutionHandler interface.
I have shown CustomRejectedExecutionHandler for better understanding the taskTwo thread condition. As taskTwo is silently discarded so that taskTwo.get() method will never be able to return data.
That's why timeout is required to be set as 1 second (taskTwo.get(1000, TimeUnit.MILLISECONDS)).
package example;
import java.util.concurrent.*;
public class ThreadPoolEx {
public static void main(String[] args) {
CustomRejectedExecutionHandler rejectionHandler = new CustomRejectedExecutionHandler();
ThreadPoolExecutor executorService =
new ThreadPoolExecutor(1, 1, 1L,
TimeUnit.MINUTES,
new SynchronousQueue<Runnable>(),
rejectionHandler
);
Future taskOne = executorService.submit(() -> {
try {
System.out.println("taskOne is going to sleep");
Thread.sleep(2000);
System.out.println("taskOne is wake up");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Future taskTwo = executorService.submit(() -> System.out.println("task two is working"));
try {
System.out.println("task one ,result: " + taskOne.get());
System.out.println("isTerminating "+ executorService.isTerminating());
System.out.println("getActiveCount "+ executorService.getActiveCount());
System.out.println("is cancelled " + taskTwo.isCancelled());
System.out.println("is isDone " + taskTwo.isDone());
System.out.println("task two, result: " + taskTwo.get(1000, TimeUnit.MILLISECONDS));
} catch (Exception e) {
}
executorService.shutdown();
}
}
class CustomRejectedExecutionHandler implements RejectedExecutionHandler {
#Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println(r.toString() + " is rejected");
}
}
The timeout on b.wait(1000) instruction is not executing after 1 second.
I will appreciate some help on how to execute the timeout on the wait() method.
protected void onCreate(Bundle savedInstanceState) {
ThreadB b = new ThreadB();
b.start();
synchronized (b) {
try {
long start = System.currentTimeMillis();
Log.i(TAG, "Before Wait has started "+start);
b.wait(1000);
long finish = System.currentTimeMillis();
Log.i(TAG, "After Wait has finished "+finish);
} catch (InterruptedException e) {
Thread.interrupted();
}
}
}
class ThreadB extends Thread {
#Override
public void run() {
synchronized (this) {
long start = System.currentTimeMillis();
Log.i(TAG, "*** Thread Start "+start);
Random ran = new Random();
for (int i = 0; i < 1E7; i++) {
Math.sin(ran.nextDouble());
}
long finish = System.currentTimeMillis();
Log.i(TAG, "*** Thread Finish "+finish);
notify();
}
}
}
Your program has a "race" to acquire the lock on the ThreadB object. If the main thread wins the race, the timeout logic works. If the new thread wins, the main thread has to wait for the new thread to finish so that it can grab the lock, and after that then it will call Object.wait and sleep for 1 second.
One quick fix is to make sure that the main thread has the lock before the new thread starts:
ThreadB b = new ThreadB();
synchronized (b) {
b.start();
try {
long start = System.currentTimeMillis();
....
}
}
A better solution is to start using the higher level concepts in the java.util.concurrent library. Instead of creating a new thread, send a task to be computed by a thread pool:
ExecutorService threadPool = Executors.newFixedThreadPool(1);
Future<?> submit = threadPool.submit(() -> {
// ThreadB computation logic
});
and then specify a timeout to wait for its results:
try {
submit.get(1, TimeUnit.SECONDS);
} catch (Exception e) {
// handle timeout, interruption, exceptions
}
Note that on Android, it's not a great idea make the main thread block or wait, even if it's for only 1 second.
I have the following java code, that uses the ScheduledExecuterService. Basically, there are two important calls made in this method: 1. the integrationMonitor.Processor(...) and 2. the runIntegrationSynching() methods.
The scheduler will make sure that these methods execute according to the time interval. Recently however, I've had the problem where processing of these two methods are very long. If the user then sets the timer interval to too low, the next processing cycle will start, even before the previous one finished.
Someone here suggested I use semaphores to do the synchronization, and I did - it works for one of my test cases, but not the other one.
I am using a semaphore to prevent a new schedule cycle to start, if a previous one is still busy. How can I know when a thread finished so that I can release the semaphore?
Here is the code:
static Semaphore semaphore = new Semaphore(1);
final ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleWithFixedDelay(new Runnable() {
#Override
public void run() {
try {
semaphore.acquire();
catch(InterruptedException e1) {}
runIntegrationSynching();
try {
semaphore.release();
} catch(InterruptedException e1) {}
Thread thread = new Thread(){
public void run(){
IntegrationMonitor intgrationMonitor = new IntegrationMonitor();
try {
semaphore.acquire();
} catch(InterruptedException e1) {}
intgrationMonitor.Processing(configXML, rcHost, alarmMonitorMap, blocker);
try {
semaphore.release();
} catch(InterruptedException e1) {}
if(intgrationMonitor != null){
intgrationMonitor = null;
}
}
};
LOGGER.info("Attempting to start the thread for RC " + rcHost + ". Thread ID:" + thread.getId());
thread.start();
}
},2,2,TimeUnit.MINUTES);
I am trying to understand countDownLatch and I have this program but I do not know why my program is not returning and not finishing.
package countDownLatches;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class Processor implements Runnable {
CountDownLatch latch;
public Processor(CountDownLatch latch) {
this.latch = latch;
}
public void run() {
System.out.println("thread started: ");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
}
}
public class App {
public static void main(String args[]) {
CountDownLatch latch = new CountDownLatch(3);
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < 3; i++) {
executorService.submit(new Processor(latch));
}
try {
latch.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("task completed");
}
}
You need to shut down the executor service. Add this line after the for loop:
executorService.shutdown();
An alternative method that waits for all actively executing tasks to terminate is
executorService.awaitTermination();
You can read more in the ExecutorService Javadoc.
You need to shutdown your executor service properly. Or it will wait for new tasks indefinitely.
Add:
executorService.shutdown();
Before:
System.out.println("task completed");
I think, that the main reason, why it was done like that in java api, is that executorService may receive tasks from multiple threads (other than main), so - why should it stop, when there is no more actions in the main thread? Yes, I believe, it should not.