So I have some Callable tasks, sensitive to interruptions, which I submit to the ExecutorService using invokeAll. After 5 seconds from another method I call executorService.shutdownNow after which I call the awaitTermination, which returns true, so all seems good. The problem is the executor never terminates.
Due to logging I know that each one of my tasks finished.
nevertheless the invokeAll still blocks on f.get when i is equal to the number of threads of the executor:
The following code is obtained from AbstractExecutorService + some logging.
#Override
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException {
if (tasks == null) throw new NullPointerException();
ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
boolean done = false;
try {
List<Callable<T>> list = new ArrayList<Callable<T>>();
for (Callable<T> t : tasks) {
list.add(t);
RunnableFuture<T> f = newTaskFor(t);
futures.add(f);
execute(f);
}
for (int i = 0, size = futures.size(); i < size; i++) {
Future<T> f = futures.get(i);
if (!f.isDone()) {
log.info("Future %s is not done!. Task %s", i, list.get(i));
try {
log.info("Get from future %s", i);
// NEXT LINE BLOCKS FOR i= NUMBER OF THREADS
f.get();
log.info("Got result from future %s", i);
} catch (CancellationException ignore) {
} catch (ExecutionException ignore) {
}
}
}
log.info("Obtained all!");
done = true;
return futures;
} finally {
if (!done) for (int i = 0, size = futures.size(); i < size; i++)
futures.get(i).cancel(true);
}
}
Am I not suppose to use invokeAll with shutdown? I guess not, after all they are in the same class. Why does it get blocked, only when i= the number of threads of the executor?
Yes, you're not suppose to use invokeAll with shutdown. At least this is what I understand, correct me if I'm wrong.
The shutdownNow method:
public List<Runnable> shutdownNow() {
...
checkShutdownAccess();
advanceRunState(STOP);
interruptWorkers();
tasks = drainQueue();
...
}
The only thing is does is interrupt working threads and remove the rest of the runnables from the working queue, see drainQueue. ShutdownNow/Shutdown does not modify the futures in our invokeAll method
So what happens in my case is that for an Executor with N threads, I invoke 300 jobs, each of them take more than 1 minute, after 5 seconds I cancel (interrupt working threads), N threads are interrupted (0 to N-1). What happens with the rest of the futures? Nothing, the next call to f.get() (see corresponding line in the question) will block and you're stuck there. This explains why I'm always blocked on i = Number of threads.
Related
I would like to run 20 threads simultaneously to test my id generator. However, uniqueSet.add(id) is not adding id to the set. When I assert, it says set size is zero.
#Test
void should_generate_unique_id_concurrently() throws InterruptedException {
Set<Long> uniqueSet = ConcurrentHashMap.newKeySet();
final int numberOfThreads = 20;
ExecutorService service = Executors.newFixedThreadPool(numberOfThreads);
CountDownLatch latch = new CountDownLatch(numberOfThreads);
for (int i = 0; i < numberOfThreads; i++) {
service.submit(() -> {
try {
latch.countDown();
latch.await();
long id = idGenerator.nextId();
uniqueSet.add(id);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
assertEquals(numberOfThreads, uniqueSet.size());
}
The uniqueSet.add(id) probably is working just fine. But most likely, none of those tasks is able to execute that line before the main thread asks for the size of the set.
Each of your task calls latch.countDown() before it does anything else. That means, none of the tasks will be able to do anything else until all twenty of them have been started.
Meanwhile, your main thread asks for the size of the set immediately after it submits the last task to the thread pool. The main thread already is running at that point. Probably most of the pool threads are sleeping in latch.await() The ones that aren't haven't even got that far yet. The main thread probably always calls uniqueSet.size() before any of the worker threads reaches the uniqueSet.add(id) line.
#VGR suggested a good solution to your problem: After your main thread has submitted the twenty tasks, and before it checks the size of the set, it could shut the thread pool down:
for (int i = 0; i < numberOfThreads; i++) {
service.submit(...);
}
// Tell the `service` to refuse new tasks, and to shut down
// _after_ all of the pending tasks have completed.
service.shutdown();
// Wait until all of the tasks have completed.
service.awaitTermination();
assertEquals(numberOfThreads, uniqueSet.size());
This is a simplified example I did to expose my problem. I have some task doSomeWork() that I handle in a multihreading fashion using ExecutorService (4 threads at a time max). However, if any of the threads/tasks generates an exception, I would like to:
Stop any further tasks from being processed.
Catch the exception at the main thread level.
public static void main(String[] args) {
final ExecutorService threadPool = Executors.newFixedThreadPool(4);
final ExecutorCompletionService<Void> completionService = new ExecutorCompletionService<>(threadPool);
try {
for (int i = 0; i < 10; i++) {
int b = i;
completionService.submit(() -> doSomeWork(b));
}
threadPool.shutdown();
threadPool.awaitTermination(8, TimeUnit.HOURS);
System.exit(0);
} catch (Exception e) {
System.out.println("Something wrong happened: " + e.getMessage());
}
System.exit(1);
}
//This function have 50% odds of throwing an exception
public static Void doSomeWork(int i) throws Exception {
Thread.sleep(500);
if ((Math.random() > 0.5))
{
System.out.println("I have reached indice: " + i);
}
else
{
throw new Exception("I couldn't handle indice " + i);
}
return null;
}
Currently, an execution would output something like this:
I have reached indice: 0
I have reached indice: 2
I have reached indice: 1
I have reached indice: 4
I have reached indice: 6
I have reached indice: 7
I have reached indice: 5
I have reached indice: 9
As you can see, indice 3 is missing, nevertheless the execution of the remaining threads completed. It also didn't output anything about the exception.
My desired output would be something like this:
I have reached indice: 0
I have reached indice: 2
I have reached indice: 1
Something wrong happened: I couldn't handle indice 3
Other solutions I found around this problem were using a callable with a future but in a blocking fashion. I can't block the execution of other threads while waiting for the future otherwise this whole multithreading is pointless.
You can do that using CompletableFuture. This is your main function I tested:
final ExecutorService executorService = Executors.newFixedThreadPool(4);
final List<CompletableFuture<Void>> all = new ArrayList<>();
try {
for (int i = 0; i < 10; i++) {
int b = i;
CompletableFuture<Void> v = CompletableFuture.runAsync(() -> {
try {
doSomeWork(b);
} catch (Exception e) {
throw new RuntimeException(e);
}
},
executorService);
all.add(v);
}
CompletableFuture<Void> placeholder = CompletableFuture.allOf(all.toArray(new CompletableFuture[0]));
failFast(all, placeholder);
System.out.println("All tasks ended");
} catch (Exception e) {
System.out.println("Something wrong happened: " + e.getMessage());
} finally {
executorService.shutdownNow();
}
Utility function to make the joint future fail as soon as one of them is failed (or when all of them are completed):
private static <T> void failFast(List<CompletableFuture<T>> futures, CompletableFuture<T> joint) {
while (true) {
if (joint.isDone()) {
return;
}
for (CompletableFuture<T> future : futures) {
if (future.isCompletedExceptionally()) {
return;
}
}
}
}
And this is the output I get:
I have reached indice: 1
I have reached indice: 7
I have reached indice: 5
I have reached indice: 4
Something wrong happened: java.lang.RuntimeException: java.lang.Exception: I couldn't handle indice 0
Explanation:
The method CompletableFuture.runAsync() allows you to provide with a Runnable (your doSomeWork) and an executor with a certain number of threads. Here, I pass an executor with 4 threads (as you did in your example).
Inside the runnable, I don't only run the doSomeWork function but I also catch Exception and throw a RuntimeException (need to do that because Lambdas do not support checked exceptions, so I need to wrap it into a runtime one but it will still interrupt execution and be catched by your main).
Each time I create a new CompletableFuture<Void> for the task with the given index i, I will store this result into a list of completable futures.
The for loop will take nothing to execute, since the completable futures run asynchronously.
Hence, I create a joint completable future with CompletableFuture.allOf(...) and then I use the utility function failFast on this future in order to stop as soon as one of the task is failed (or to continue until all of them are complete).
So basically as soon as one of the futures fails throwing an exception, the joint future is considered to be completed and will hence leave the handle to your main thread which is, meanwhile, being hit by the RuntimeException that was thrown inside the lambda expression.
Note: thanks to Thomas' comment, I've updated the code to use an ExecutorService instead of a simple Executor. That allows you to have a call to shutdownNow() inside your finally block after you catch the exception.
As Thomas suggests, also, you may directly throw a RuntimeException inside your doSomeWork function so you don't need to catch and wrap inside the lambda expression.
Other note: #matt made me notice something I didn't know. The .allOf() future will be completed when ALL futures are completed, whether successfully or not.
Hence, as he pointed out, my solution wouldn't work as is. I've edited again the answer to take his comment into account, thanks #matt for making me notice.
It sounds like you've excluded a correct way to do this, based on an incorrect assumption. Keep your futures.
List<Future<?>> futures = new ArrayList<>();
Then when you submit.
futures.add( completionService.submit( () -> doSomeWork(b) ) );
Now, you can check the futures status in your main thread.
for(Future<?> f: futures){
try{
f.get();
} catch( ExecutionException e){
//execution exception handled on the main thread.
completionService.shutdownNow();
} catch( InterruptedException ie){
//what should happen here.
}
}
That way, shutdownNow gets called, so all of the non-started tasks get returned and will not start.
You could use a timeout with get to check every task since some will be running in parallel.
Here is a complete compilable example.
import java.util.concurrent.*;
import java.util.*;
public class ExecutorJunk{
static int count = 0;
static void task(){
int z = count++;
if(z == 3){
throw new RuntimeException("z is 3");
}
System.out.println("z: " + z);
try{ Thread.sleep(1500);} catch(InterruptedException e){};
}
public static void main(String[] args){
ExecutorService service = Executors.newFixedThreadPool(4);
List<Future<?>> all = new ArrayList<>();
for(int i = 0; i<10; i++){
all.add( service.submit(ExecutorJunk::task) );
}
service.shutdown();
try{
while(!service.isTerminated()){
for(Future f: all){
try{
f.get(1, TimeUnit.MILLISECONDS);
} catch( TimeoutException toe){
//pass.
}
}
}
} catch(Exception e){
System.out.println( service.shutdownNow().size() + " tasks not started");
e.printStackTrace();
}
}
}
When I run this I get.
z: 0
z: 1
z: 2
z: 4
5 tasks not started
java.util.concurrent.ExecutionException: java.lang.RuntimeException: z is 3
...
It probably could be done a bit smarter. Such as purging the list of futures as get succeeds, instead of using a timeout just check the futures if they're done, then doing a future.get.
I have Service.class with start() method:
public void start() {
for (int i = 0; i < companiesList.size(); i++) {
asychronous.someAsynchronous(...);
}
log.info("Start method has finished");
}
I have Asynchronous.class with someAsynchronous() method:
#Async("threadPoolTaskExecutor")
public CompletableFuture<Void> someAsynchronous(some_parameters) {
//do some stuff
return null;
}
The log.info() shows up before someAsynchronous() methods has finished.
How to force it to wait for log.info() until someSynchronous() methods in loop will finish? Btw: Asynchronous threads are still running after finishing loop.
The CompletableFuture<Void> calls are requested to be executed but after all of them start in separate threads, the for-loop finishes and the log is printed even before any of them finished. This is the advantage of the asynchronous processing - you don't care about their results and how much time they took to execute.
To achieve you want, you have to periodically check whether all of them are finished before you proceed to the log outoput.
// Adds executions to the List
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (int i = 0; i < companiesList.size(); i++) {
futures.add(asychronous.someAsynchronous(...));
}
// Periodical check
Iterator<CompletableFuture<Void>> iterator = futures.iterator();
while (iterator.hasNext()) {
CompletableFuture<Void> future = iterator.next(); // get the next one
if (future.isDone()) { // if finished...
//... // ... do an action
iterator.remove(); // ... and remove from the Iterator
}
if (!iterator.hasNext()) { // if you reach the end
iterator = futures.iterator(); // ... repeat the remaining Futures
}
}
log.info("Start method has finished");
Note this method doesn't finish until all of the executions are done.
Edit: Thanks to #Kayaman who suggested using a single method dedicated for that replacing the whole Iterator logics. The futures must be an array:
// Adds executions to the List
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (int i = 0; i < companiesList.size(); i++) {
futures.add(asychronous.someAsynchronous(...));
}
// Join the completion of all the threads
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
log.info("Start method has finished");
This code I have is not executing tasks in parallel,
it only executes the code in this case once (whatever is in the for loop, but it should be 2) :
public class mqDirect {
public static void main(String args[]) throws Exception {
int parallelism = 2;
ExecutorService executorService =
Executors.newFixedThreadPool(parallelism);
Semaphore semaphore = new Semaphore(parallelism);
for (int i = 0; i < 1; i++) {
try {
semaphore.acquire();
// snip ... do stuff..
semaphore.release();
} catch (Throwable throwable) {
semaphore.release();
}
executorService.shutdownNow();
}
}
}
In Java the main way to make code work in parallel is to create a Thread with a new Runnable as a constructor parameter. You then need to start it.
There are many tutorials to help you get this to happen properly.
As your code stands you are merely creating an ExecutorService (and not using it), creating a Semaphore (which should be done in the thread but isn't), performing some process and then shutting down the Executor.
BTW: ShutDownNow is probably not what you want, you should just use ShutDown.
OK, So I found this good tutorial
http://programmingexamples.wikidot.com/threadpoolexecutor
And I have done something like
public class mqDirect {
int poolSize = 2;
int maxPoolSize = 2;
long keepAliveTime = 10;
ThreadPoolExecutor threadPool = null;
final ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(
5);
public mqDirect()
{
threadPool = new ThreadPoolExecutor(poolSize, maxPoolSize,
keepAliveTime, TimeUnit.SECONDS, queue);
}
public void runTask(Runnable task)
{
threadPool.execute(task);
System.out.println("Task count.." + queue.size());
}
public void shutDown()
{
threadPool.shutdown();
}
public static void main (String args[]) throws Exception
{
mqDirect mtpe = new mqDirect();
// start first one
mtpe.runTask(new Runnable()
{
public void run()
{
for (int i = 0; i < 2; i++)
{
try
{
System.out.println("First Task");
runMqTests();
Thread.sleep(1000);
} catch (InterruptedException ie)
{
}
}
}
});
// start second one
/*
* try{ Thread.sleep(500); }catch(InterruptedException
* ie){}
*/
mtpe.runTask(new Runnable()
{
public void run()
{
for (int i = 0; i < 2; i++)
{
try
{
System.out.println("Second Task");
runMqTests();
Thread.sleep(1000);
} catch (InterruptedException ie)
{
}
}
}
});
mtpe.shutDown();
// runMqTests();
}
And it works !
But the problem is , this duplicated code ... runMqtests() is the same task, is there a way to specify it to run in parallel without duplicating the code?
The example I based this off is assuming each task is different.
This code I have is not executing tasks in parallel, it only executes the code in this case once (whatever is in the for loop, but it should be 2) :
Just because you instantiate an ExecutorService instance doesn't mean that things magically run in parallel. You actually need to use that object aside from just shutting it down.
If you want the stuff in the loop to run in the threads in the service then you need to do something like:
int parallelism = 2;
ExecutorService executorService = Executors.newFixedThreadPool(parallelism);
for (int i = 0; i < parallelism; i++) {
executorService.submit(() -> {
// the code you want to be run by the threads in the exector-service
// ...
});
}
// once you have submitted all of the jobs, you can shut it down
executorService.shutdown();
// you might want to call executorService.awaitTermination(...) here
It is important to note that this will run your code in the service but there are no guarantees that it will be run "in parallel". This depends on your number of processors and the race conditions inherent with threads. For example, the first task might start up, run, and finish its code before the 2nd one starts. That's the nature of threaded programs which are by design asynchronous.
If, however, you have at least 2 cores, and the code that you submit to be run by the executor-service takes a long time to run then most likely they will be running at the same time at some point.
Lastly, as #OldCurmudgeon points out, you should call shutdown() on the service which allows current jobs already submitted to the service to run as opposed to shutdownNow() which cancels and queued jobs and also calls thread.interrupt() on any running jobs.
Hope this helps.
I am writing a thread pool utility in my multithreading program. i just need to validate the following methods are correct and are they return the right values for me. i am using a LinkedBlockingQueue with size of 1. and also I refer to the java doc and it always says 'method will return approximate' number phrase. so i doubt weather following conditions are correct.
public boolean isPoolIdle() {
return myThreadPool.getActiveCount() == 0;
}
public int getAcceptableTaskCount() {
//initially poolSize is 0 ( after pool executes something it started to change )
if (myThreadPool.getPoolSize() == 0) {
return myThreadPool.getCorePoolSize() - myThreadPool.getActiveCount();
}
return myThreadPool.getPoolSize() - myThreadPool.getActiveCount();
}
public boolean isPoolReadyToAcceptTasks(){
return myThreadPool.getActiveCount()<myThreadPool.getCorePoolSize();
}
Please let me know your thoughts and suggestions.
UPDATE
interesting thing was if pool returns me there are 3 threads available from the getAcceptableTaskCount method and when i pass 3 tasks to the pool some times one task got rejected and it is handle by RejectedExecutionHandler. some times pool will handle all the tasks i passed. i am wondering why pool is rejected the tasks since i am passing tasks according to the available thread count.
--------- implementation of the answer of gray---
class MyTask implements Runnable {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("exec");
}
}
#Test
public void testTPool(){
ExecutorService pool = Executors.newFixedThreadPool(5);
List<Future<MyTask>> list = new ArrayList<Future<MyTask>>();
for (int i = 0; i < 5; i++) {
MyTask t = new MyTask();
list.add(pool.submit(t, t));
}
for (int i = 0; i < list.size(); i++) {
Future<MyTask> t = list.get(i);
System.out.println("Result -"+t.isDone());
MyTask m = new MyTask();
list.add(pool.submit(m,m));
}
}
This will print Result -false in the console meaning that task is not complete.
From your comments:
i need to know that if pool is idle or pool can accept the tasks. if pool can accept, i need to know how much free threads in the pool. if it is 5 i will send 5 tasks to the pool to do the processing.
I don't think that you should be doing the pool accounting yourself. For your thread pool if you use Executors.newFixedThreadPool(5) then you can submit as many tasks as you want and it will only run them in 5 threads.
so i get the first most 5 tasks from the vector and assign them to the pool.ignore the other tasks in the vector since they may be update / remove from a separate cycle
Ok, I see. So you want to maximize parallelization while at the same time not pre-loading jobs? I would think that something like the following pseudo code would work:
int numThreads = 5;
ExecutorService threadPool = Executors.newFixedThreadPool(numThreads);
List<Future<MyJob>> futures = new ArrayList<Future<MyJob>>();
// submit the initial jobs
for (int i = 0; i < numThreads; i++) {
MyJob myJob = getNextBestJob();
futures.add(threadPool.submit(myJob, myJob));
}
// the list is growing so we use for i
for (int i = 0; i < futures.size(); i++) {
// wait for a job to finish
MyJob myJob = futures.get(i);
// process the job somehow
// get the next best job now that the previous one finished
MyJob nextJob = getNextBestJob();
if (nextJob != null) {
// submit the next job unless we are done
futures.add(threadPool.submit(myJob, myJob));
}
}
However, I don't quite understand how the thread count would change however. If you edit your question with some more details I can tweak my response.