Executors NewFixedThreadPool not giving the expected result - java

I am trying to execute multiple threads in scala and for a simple test I run this code:
Executors.newFixedThreadPool(20).execute( new Runnable {
override def run(): Unit = {
println("Thread Started!")
}
})
As far as I could understand, it would create 20 threads and call the
print function, but this is not what's happening. It creates only one
thread, executes the print and hangs.
Can someone explain me this phenomena?

The reason it hangs is that you don't shut down the ExecutorService. In Java (sorry, not familiar with Scala):
ExecutorService executor = Executors.newFixedThreadPool(20); // or 1.
executor.execute(() -> System.out.println("..."));
executor.shutdown();
As to why you only see the message once: you create 20 threads, and give just one of them work. Threads won't do anything if you don't give them anything to do.
I think you assumed that this code would execute the runnable on each thread in the pool. That's simply not the case.
If you want to actually do this 20 times in different threads, you need to a) submit 20 runnables; b) synchronise the runnables in order that they actually need to run on separate threads:
CountdownLatch latch = new CountdownLatch(1);
ExecutorService executor = Executors.newFixedThreadPool(20);
for (int i = 0; i < 20; ++i) {
executor.execute(() -> {
latch.await(); // exception handling omitted for clarity.
System.out.println("...");
});
}
latch.countdown();
executor.shutdown();
The latch here ensures that the threads wait for each other before proceeding. Without it, the trivial work could easily be done on one thread before submitting another, so you wouldn't use all of the threads in the pool.

Related

Why the order was not guaranteed by Executors.newSingleThreadExecutor()? [duplicate]

This question already has answers here:
wait until all threads finish their work in java
(17 answers)
How to wait for all threads to finish, using ExecutorService?
(27 answers)
Closed 3 months ago.
I am using JDK/Java 19 in Windows 11 x64, IntelliJ IDEA 2022 Ultimate.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ZooInfo {
public static void main(String[] args) {
ExecutorService executorService = null;
Runnable runnable1 = () -> System.out.println("Printing zoo inventory");
Runnable runnable2 = () -> {
for (int i = 0; i < 3; i++) {
System.out.println("Printing record " + i);
}
};
try {
executorService = Executors.newSingleThreadExecutor();
System.out.println("Begin");
executorService.execute(runnable1);
executorService.execute(runnable2);
executorService.execute(runnable1);
System.out.println("End.");
} finally {
if (executorService != null) {
executorService.shutdown();
}
}
}
}
// Result:
// Begin
// End.
// Printing zoo inventory
// Printing record 0
// Printing record 1
// Printing record 2
// Printing zoo inventory
I read page 850, book OCP Oracle Certified Professional Java SE 11 Developer - Complete Study Guide), they said
With a single-thread executor, results are guaranteed to be executed
sequentially.
Why the order was not guaranteed by Executors.newSingleThreadExecutor() ? ("end" not at the end of line in console's result.)
shutdownAndAwaitTermination boilerplate
You neglected to wait for the executor service to complete its work.
You ignored all the boilerplate code given to you in the shutdownAndAwaitTermination method shown in the Javadoc for ExecutorService.
Add a call to that boilerplate after you submit your Runnable objects. Now your main thread will wait for the executor’s thread(s) to finish their tasks.
executorService = Executors.newSingleThreadExecutor();
System.out.println("Begin");
executorService.execute(runnable1);
executorService.execute(runnable2);
executorService.execute(runnable1);
shutdownAndAwaitTermination( executorService ) ; // Block here to wait for executor service to complete its assigned tasks.
System.out.println("End.");
Your original thread happened to finish its work earlier than did the thread of the executor service. That is the nature of independent threads: various threads accomplish various amounts of work in various amounts of time.
Project Loom
Project Loom is an effort to bring new capabilities to the Java concurrency facilities.
The structured concurrency feature being incubated now in Java 19 might make it even easier to accomplish your goal of having several tasks performed as a group on background threads.
Your program has two threads:
The main one, from which you invoke executorService.execute and all the rest.
The Executors.newSingleThreadExecutor()'s thread
The runnables you pass to the newSingleThreadExecutor will indeed be run sequentially on that thread, but it doesn't mean everything in your program runs sequentially relative to those runnables. Your main thread will keep going, unless you somehow wait on the main thread for the tasks to complete (for example, by invoking executorService.shutdown() and then awaitTermination(...) to wait for the existing jobs to finish). You could also use submit rather than execute for each runnable; that would give you back a Future, which you can then call get(...) on to wait for it to finish (you would have to do this for each runnable. executorService.invokeAll(...) makes this a bit easier.
Because main method is independent with executorService = Executors.newSingleThreadExecutor();

Thread pool not accepting new tasks

I feel like my java concurrency knowledge is getting rusty, I am trying to figure out why the thread pool doesn't accept more tasks in the following code:
ExecutorService e = Executors.newFixedThreadPool(aNumber);
// Task 1
for (int i=0; i<n; i++)
e.submit(new aRunnable());
while (!e.isTerminated());
System.out.println("Task 1 done");
// Task 2
for (int i=0; i<n; i++)
e.submit(new anotherRunnable());
while (!e.isTerminated());
System.out.println("Task 2 done");
It never gets to start Task 2, the thread "freezes" when the last task from Task 1 one is run like if it was waiting for something else to finish.
What's wrong?
It never gets to start Task 2, the thread "freezes" when the last task from Task 1 one is run like if it was waiting for something else to finish.
It is waiting. ExecutorService.isTerminated() waits for the thread pool tasks to finish after the pool has been shutdown. Since you've never called e.shutdown(); your loop will spin forever. To quote from the ExecutorService javadocs:
Returns true if all tasks have completed following shut down. Note that isTerminated is never true unless either shutdown or shutdownNow was called first.
You've not shut the service down so that will never be true. In general, anything that spins in a while loop like that is an antipattern – at the very least put a Thread.sleep(10); in the loop. Typically we use e.awaitTermination(...) but again, that's only after you've called e.shutdown();. And you don't want to shut the ExecutorService down because you are going to be submitting more tasks to it.
If you want to wait for all of your tasks to finish then submit more tasks I'd do something like the following and call get() on the Futures that are returned from the first batch of submitting tasks. Something like:
List<Future> futures = new ArrayList<Future>();
for (int i = 0; i < n; i++) {
futures.add(e.submit(new aRunnable()));
}
// now go back and wait for all of those tasks to finish
for (Future future : futures) {
future.get();
}
// now you can go forward and submit other tasks to the thread-pool
If you want to know when a specific task finishes, use an ExecutorService, which will return a Future<> (a handle that you can use to get the status of a specific job) -- the executor itself doesn't terminate until you shut it down. Think of an executor like 'batch queue' or a 'coprocessor' waiting around for you to throw some work in the hopper.
Update: Gray answered this much better than I - see his post. -- (how do people type that fast??)

Task Execution and wait for tasks to finish: Java

There is a generic queue of tasks where new tasks get added. I want to write code that will create more work in terms of tasks by adding them to the queue. The task that added the work to the queue will wait for all tasks to complete by polling the queue.
What would be the best way to implement it using Java. I was thinking of something on the lines of Simple threads by implementing a runnable interface and make it run in an infinite loop and sleep in between, wake up to see if there is any progress. If the progress is happening, keep on looping, if it has completed break out of the loop. Is there any other good and performance efficient way to implement this ?
How the tasks complete?
The tasks are submitted to a Queue. The Queue is polled by an executor and it runs the tasks.
What i want to do?
Poll that queue to see if the task has completed or is still executing.
What you're describing here, may be a rough sketch of a work queue. You could enqueue processes for asynchronous processing, wait for a notification of completion, and then terminate. This works, but there are new concurrency tools available. I recommend reading the Java Concurrency Lesson.
The new model for concurrency allows you to separate the concurrency concerns from the thread via tasks, Runnable and Callable and the ExecutorService. Rather than working directly with threads and building your own thread pool try to let the Executor do the heavy lifting for you.
...
ExecutorService ex = Executors.newSingleThreadExecutor();
....
You may hand tasks, in the form of Runnables and Callables, to the ExecutorService and receive in return Future objects which may be used to monitor the task's progress.
Future<String> f = executor.submit(new Foo());
....
class Foo implements Callable<String> {
#Override
public String call() throws Exception {
return "Bar";
}
}
You may use an ExecutorCompletionService to monitor the completion of tasks for you :
CompletionService<String> cs = new ExecutorCompletionService<String>(executor);
Future<String> f = cs.submit(new Foo());
... // Let's say you've added TASK_COUNT tasks
for (int i = 0; i < TASK_COUNT ; i++ ) {
try {
String str = cs.take().get();
if (str != null) {
System.out.println(str); //Handle the result of the Callable
continue;
}
} catch (ExecutionException ignore) {}
}
now you've received a result per callable, you can clean up your tasks using the Future f object you received earlier with cs.submit(new Foo()) , by invoking
f.cancel(true)
on each task. And finally, don't forget to clean up your executor with
executor.shutdown();
There is a lot more to concurrency than this, but I believe that the above illustrates a means to meet your needs. I'd recommend reading the JavaDoc as well.
Use java.util.concurrent.Future and a java.util.concurrent.CompletionService.
You can use Fork/Join framework from java 7

Thread Scheduling - Run threads in set order

I have a set of roughly 20 threads and i want to schedule them so they run in a set order.
Is there a way to do this. I have tried using priority and setting the priority 1-10 but the scheduler still seems to execute threads at its own order. Btw im working in Java
Is there a way to run threads in a set order ?
Thanks
regards
Mike
What you need is an ExecutorService that will run your threads one at a time, namely : newSingleThreadExecutor.
ExecutorService pool = Executors.newSingleThreadExecutor();
pool.submit(job1);
pool.submit(job2);
pool.submit(job3);
Why do you have multiple threads if you want synchronous behaviour in the first place?
If you've acquired multiple Thread objects from "something else" then you can use thread.run() to execute them in the current thread, which will, of course allow you to control the order.
You don't have to run a single threaded version if the jobs can be executed in parallel. Below is an example where you can use eight threads to run your 20 jobs:
public static void main(String[] args) {
final ExecutorService executorService = Executors.newFixedThreadPool(8);
final Queue<Integer> workItems = new ConcurrentLinkedQueue<Integer>();
for (int i = 0; i < 20; i++) {
workItems.add(i);
}
for (int i = 0; i < 20; i++) {
executorService.submit(new Runnable() {
#Override
public void run() {
final Integer workIem = workItems.poll();
// process work item
}
});
}
// await termination of the exec service using shutdown() and awaitTermination()
}
The idea is that you use an auxiliary queue to maintain the items to be processed and rely on the FIFO ordering of the queue to process the items in order and in parallel.
If the threads depend on each other, then one option would be to schedule only the first thread and have it spawn its dependent threads, which can then turn their dependent threads, etc...
You need to understand, however, that even though you may be launching threads in a particular order, as soon as they start they are off of your hands and they will be fighting for resources and the OS will time-slice their executions, which means some may get "ahead" of threads that were launched before. So if you truly need to keep the order, then I would suggest you use only one thread and let it orchestrate the tasks in a synchronized manner.

Java producer/consumer, detecting end of processing

I'm preparing an application where a single producer generates several million tasks, which will then be processed by a configurable number of consumers. Communication from producer to consumer is (probably) going to be queue-based.
From the thread that runs the producer/generates the tasks, what method can I use to wait for completion of all tasks? I'd rather not resume to any periodic polling to see if my tasks queue is empty. In any case, the task queue being empty isn't actually a guarantee that the last tasks have completed. Those tasks can be relatively long-running, so it's quite possible that the queue is empty while the consumer threads are still happily processing.
Rgds, Maarten
You might want to have a look at the java.util.concurrent package.
ExecutorService
Executors
Future
The executor framework already provides means to execute tasks via threadpool. The Future abstraction allows to wait for the completition of tasks.
Putting both together allows you coordinate the executions easily, decoupling tasks, activities (threads) and results.
Example:
ExecutorService executorService = Executors.newFixedThreadPool(16);
List<Callable<Void>> tasks = null;
//TODO: fill tasks;
//dispatch
List<Future<Void>> results = executorService.invokeAll(tasks);
//Wait until all tasks have completed
for(Future<Void> result: results){
result.get();
}
Edit: Alternative Version using CountDownLatch
ExecutorService executorService = Executors.newFixedThreadPool(16);
final CountDownLatch latch;
List<Callable<Void>> tasks = null;
//TODO: fill tasks;
latch = new CountDownLatch(tasks.size());
//dispatch
executorService.invokeAll(tasks);
//Wait until all tasks have completed
latch.await();
And inside your tasks:
Callable<Void> task = new Callable<Void>()
{
#Override
public Void call() throws Exception
{
// TODO: do your stuff
latch.countDown(); //<---- important part
return null;
}
};
You want to know where every tasks completes. I would have another queue of completed task reports. (One object/message per task) When this count reaches the number of tasks you created, they have all completed. This task report can also have any errors and timing information for the task.
You could have each consumer check to see if the queue is empty when they dequeue, and, if it is, pulse a condvar (or a Monitor, since I believe that's what Java has) on which the main thread is waiting.
Having the threads check a global boolean variable (marked as volatile) is a way to let the threads know that they should stop.
You can use join() method for each thread ..so that till all the threads are done your main thread will not end! And by this way you can actually find out whether all the threads are done or not!

Categories

Resources