Why this Future's method is blocking main thread? - java

ExecutorService executor = Executors.newFixedThreadPool(2);
Future<Integer> calculate(Integer input) {
return executor.submit(() -> {
Thread.sleep(3000);
return input * input;
});
}
public static void main(String []args) throws Exception {
Main m = new Main();
System.out.println(m.calculate(5).get());
System.out.println("Main");
We submit Callable to Executor with 2 threads, but when i tell m.calculate(5).get() it block main thread.
So, I can't understand, when and why should I use Future if it blocks the main thread and doesn't run asynchronously?

If you look into the documentation of Future::get it says: "Waits if necessary for the computation to complete, and then retrieves its result." By calling this method you agree to wait for the result in the main thread.
You can check if Future has completed by calling Future::isDone, which returns boolean.
In your scenario it can be used like this
public static void main(String []args) throws Exception {
Main m = new Main();
Future<Integer> futureInt = m.calculate(5);
// do some other asynchronous task or something in main thread while futureInt is doing its calculations
// and then call Future::get
int result = futureInt.get();
See: doc

Future is indeed a very limited abstraction, in more realistic cases you should use CompletableFuture instead. Future is a pretty old class (since java 1.5 I guess) so the understanding of the industry has gradually evolved in the field of concurrent programming,
Nevertheless, it can still be useful by itself.
What if instead of spawning one future and immediately calling get on it, we would like to spawn many tasks and store the result in some list:
List<Future<Integer>> futures = new ArrayList<>(10);
for(int i = 0 ; i< 10; i++) {
futures.add(calculate(<some_integer>));
}
// at this point all futures are running concurrently
for(int i = 0 ; i < 10; i++) {
futures.get(i).get(); // will either return immediately or we'll block the main thread but the point is that all the calculations will run concurrently
}

Related

How to create multiple threads inside of a for loop

Hi I am somewhat new to Java.
I have a method that takes in a map, and for each key value pair in the map it writes to a file.
I want to have a thread per key,value pair in the map running so that I can create multiple files at the same time. Not sure what is the proper way of doing this or how to use executor service to do get this done.
Here is a very simple example of what I'm trying to. Instead of writing all the code for writing the file Im just using system.out.println in the example:
public class CityWriter
{
public static void main(String []args)
{
LinkedHashMap<Integer, ArrayList<City>> stateNumCitiesMap = new LinkedHashMap<Integer, ArrayList<City>>();
stateNumCitiesMap = retrieveStateCitiesMap();
int numOfThreadsToExecuteAtATime = 10;
ExecutorService executor = Executors.newFixedThreadPool(numOfThreadsToExecuteAtATime);
for(Integer key : stateNumCitiesMap.keySet()) //Could have up to 50 key,values in map
{
executor.execute(writeCitiesOfStateToFile(key, StateNumCitiesMap.get(key)));
}
executor.shutdown();
}
public LinkedHashMap<Integer, ArrayList<Cities>> writeCitiesOfStateToFile(int stateNum, List<City> citiesList)
{
for(City city : citiesList)
{
System.out.println(stateNum +" "+ city);
}
}
}//end of class
My problem is that it doesn't seem like it is executing threads in parallel here. Also I don't want to run more than 10 threads at a time even though the for loop will call the executor 50 times.
please let me know what would be the most efficient way to do this.
Actually, if i understood your question well, your code does exactly what you want(of course if we omit all syntax errors in your code snippet):
It does not spawn more than 10 threads, because you have specified here Executors.newFixedThreadPool(10) how many threads you want
All your x map entries will be assigned to executor as potential job. Then executor will run each of them in parallel with all 10 threads(but no more than 10 jobs at once)
You can try this snippet out and check that several threads are doing the job in parallel:
public static void main(String[] args) {
Map<Integer, List<String>> stateNumCitiesMap = new LinkedHashMap<>();
for (int i = 0; i < 100; i++) {
stateNumCitiesMap.put(i, Collections.singletonList("ABC"));
}
ExecutorService executor = Executors.newFixedThreadPool(10);
for (Integer key : stateNumCitiesMap.keySet()) {
executor.execute(() -> writeCitiesOfStateToFile(key, stateNumCitiesMap.get(key)));
}
executor.shutdown();
}
public static void writeCitiesOfStateToFile(int stateNum, List<String> citiesList) {
for (String city : citiesList) {
System.out.println(stateNum + " " + Thread.currentThread().getName());
}
}
In case you don't want to give a job one by one to the executor, you can pass a batch of them once.
public static void main(String[] args) throws InterruptedException {
Map<Integer, List<String>> stateNumCitiesMap = new LinkedHashMap<>();
for (int i = 0; i < 100; i++) {
stateNumCitiesMap.put(i, Collections.singletonList("ABC"));
}
ExecutorService executor = Executors.newFixedThreadPool(10);
List<Callable<Void>> jobs = new ArrayList<>();
for (Integer key : stateNumCitiesMap.keySet()) {
jobs.add(() -> {
writeCitiesOfStateToFile(key, stateNumCitiesMap.get(key));
return null;
});
}
executor.invokeAll(jobs);
executor.shutdown();
}
public static void writeCitiesOfStateToFile(int stateNum, List<String> citiesList) {
for (String city : citiesList) {
System.out.println(stateNum + " " + Thread.currentThread().getName());
}
}
You can use "invokeAll" method for multiple executions and even get their results (as done or not). It will use 10 thread for them even they are 50. The results will be returned when all tasks are completed. Something like below, take it as pseudo.
Callable<int> callableTask = (fileName) -> {
// implement write to the file
return 0;
};
ExecutorService executor = Executors.newFixedThreadPool(10);
List<Callable<int>> tasksList;
for(City city : citiesList)
{
tasksList.add(callableTask(city.toString()));
}
executor.invokeAll(tasksList);
In java you need to provide the runnable interface to any object you wish to run in a thread , you are not doing this and this is what the executor is expecting.
executor.execute(() -> your function )
is actually
executor.execute(new Runnable() {
#Override
public void run() {
// your code
}
});
the method does not implement runnables , only in the run method of runnable will it be threaded
the reason is that the executor uses a kind of observer pattern and you subscribe the runnable to it , the executor then runs the run method
from java docs :
The Runnable interface should be implemented by any class whose instances are intended to be executed by a thread. The class must define a method of no arguments called run.
This interface is designed to provide a common protocol for objects that wish to execute code while they are active. For example, Runnable is implemented by class Thread. Being active simply means that a thread has been started and has not yet been stopped.
Can also make the method return a runnable itself
public static Runnable writeCitiesOfStateToFile(params) {
return () -> System.out.println(params);
}
Executor#execute may be synchronous
You said:
it doesn't seem like it is executing threads in parallel here
You did not explain the reason for that perception.
But, FYI, that may indeed be the case. You called the execute method on your ExecutorService.
for(Integer key : stateNumCitiesMap.keySet()) //Could have up to 50 key,values in map
{
executor.execute(writeCitiesOfStateToFile(key, StateNumCitiesMap.get(key)));
}
That execute method is inherited from the Executor interface, the super-interface of ExecutorService. That interface, and its method, are documented as maybe running your task asynchronously. To quote the Javadoc:
The command may execute in a new thread, in a pooled thread, or in the calling thread, at the discretion of the Executor implementation.
So you may indeed be seeing sequential non-thread synchronous execution rather than async.
From my reading of the ExecutorService methods submit, invokeAll, & invokeAny, these seem to be promising to always run asynchronously.
I do not believe such synchronous behavior is happening though, given your choice of ExecutorService implementation. Your call to Executors.newFixedThreadPool produces an object of type ThreadPoolExecutor. Looking briefly at the source code of that concrete class’ execute method, it appears to always work asynchronously (though I am not entirely sure).
Nevertheless, it would seem that we should not always assume async execution when using Executor#execute.

What happens if a Runnable executed several times in an ExecutorService

What happens if a thread has been executed same time more than once. Lets say I have thread like
private Runnable mySampleThread() {
return new Runnable() {
#Override
public void run() {
//something is going on here.
}
};
}
And I created an ExecutorService with fixed thread pool of 10. What happens if I execute mySampleThread 10 times in this ExecutorService.
Something like below,
ExecutorService mySampleExecutor = Executors.newFixedThreadPool(10);
while (i <= 10) {
mySampleExecutor.execute(mySampleThread);
i++;
}
Answer is very simple. Executor will execute Runnable object (it's not the Thread object) as described in documentation Interface Executor
Executes the given command at some time in the future. The command may execute in a new thread, in a pooled thread, or in the calling thread, at the discretion of the Executor implementation.
Basically, Executor will pick up one thread of it's internal pool (ThreadPoolExecutor), assign runnable to it a execute run() method.
Firstly elaborate your problem or query.
Nevertheless, assuming that you are calling the method "mySampleThread()" without missing brackets. This method actually returns a new Runnable object every time, so you are passing a new runnable all 10 times to executor. And it means you are submitting 10 different tasks to executor. So if executor creates different thread for every task (that depends upon its implementation), then whatever you code inside run() will be executed 10 times in 10 different threads.
And as described in other answers, the runnable object being passed to executor is not a thread.
Hope it clarifies.
By the way, you may try running the program.
As other answers clearly state, there will be as many new threads as the number of calls (might be less due to used executor, I'm focusing on Runnable reusage, limiting number of threads with executor is well explained in other answers). All of them created with single Runnable object.
What's worth mentioning, and I personally made use of this quite a few times - this is one of the ways to share data between multiple threads as all of these threads share Runnable that was used for creation. Synchronization issues come into play at this point, but that's another story.
Here's code to show the typical usage and the aforementioned synchronization problem.
import java.util.concurrent.ExecutorService;
class MyThread implements Runnable {
public int counter = 0;
#Override
public void run() {
for (int i = 0; i < 10000; i++) {
counter++;
}
}
}
class MySynchronizedThread implements Runnable {
public int counter = 0;
#Override
public void run() {
for (int i = 0; i < 10000; i++) {
synchronized (this) {
counter++;
}
}
}
}
public class RunnableTest {
public static void main(String[] args) throws InterruptedException {
MyThread runnableObject = new MyThread();
ExecutorService ex = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
ex.execute(runnableObject);
}
ex.shutdown();
ex.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
System.out
.println("Without synchronization: " + runnableObject.counter);
MyThread runnableSynchronizedObject = new MyThread();
ExecutorService ex2 = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
ex2.execute(runnableSynchronizedObject);
}
ex2.shutdown();
ex2.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
System.out.println("Without synchronization: "
+ runnableSynchronizedObject.counter);
}
}
There will be no differences in mySampleExecutor.execute(mySampleThread);, mySampleThread method return a new Runnable object. every thread will have it's own Frames

Synchronized Block inside the run method

Does using a synchronized block inside the run method makes any sense? I thought it does, as long as I'm using a relevant lock, not the instance of Runnable containing this run method. Reading the answers to similar questions on stackoverflow seemed to confirm this. I tried to write some simple code to test it and the synchronized block inside the run method doesn't prevent from data corruption:
public class Test {
public Test() {
ExecutorService es = Executors.newCachedThreadPool();
for (int i = 0; i < 1000; i++) {
es.execute(new Runnable() {
#Override
public void run() {
synchronized (lock) {
sum += 1;
}
}
});
}
es.shutdown();
while(!es.isTerminated()) {
}
}
private int sum = 0;
private final Object lock = new Object();
public static void main(String[] args) {
Test t = new Test();
System.out.println(t.sum);
}
}
Why this code generates incorrect results? Is this because the synchronized block or some other mistake? I feel like I'm missing something basic here.
It's possible your executor encounters some sort of unexpected error. If that happens you won't know it because you are not getting any return value to check.
Try switching to submit() instead of execute() and store a list of Future instances the Executor gives you. If the final sum is less than 1000, iterate the futures and get() each one. If an exception is raised you'll see what happened with that particular runnable task.
Apart from your simple example, which looks OK, you should be careful with synchronization in Runnables to prevent them from blocking each other when one Runnable waits for some resource to be released only by another Runnable later in the queue that has not started yet and never will since the current waiting Runnable must finish first.
With enough worker Threads executing the jobs this is less likely to occur, though.

In Java, how to pass the objects back to Main thread from worker threads?

In Java, how to pass the objects back to Main thread from worker threads? Take the following codes as an example:
main(String[] args) {
String[] inputs;
Result[] results;
Thread[] workers = new WorkerThread[numThreads];
for (int i = 0; i < numThreads; i++) {
workers[i] = new WorkerThread(i, inputs[i], results[i]);
workers[i].start();
}
....
}
....
class WorkerThread extends Thread {
String input;
int name;
Result result;
WorkerThread(int name, String input, Result result) {
super(name+"");
this.name = name;
this.input = input;
this.result = result;
}
public void run() {
result = Processor.process(input);
}
}
How to pass the result back to main's results[i] ?
How about passing this to WorkerThread,
workers[i] = new WorkerThread(i, inputs[i], results[i], this);
so that it could
mainThread.reults[i] = Processor.process(inputs[i]);
Why don't you use Callables and an ExecutorService?
main(String[] args) {
String[] inputs;
Future<Result>[] results;
for (int i = 0; i < inputs.length; i++) {
results[i] = executor.submit(new Worker(inputs[i]);
}
for (int i = 0; i < inputs.length; i++) {
Result r = results[i].get();
// do something with the result
}
}
#Thilo's and #Erickson's answers are the best one. There are existing APIs that do this kind of thing simply and reliably.
But if you want to persist with your current approach of doing it by hand, then the following change to you code may be sufficient:
for (int i = 0; i < numThreads; i++) {
results[i] = new Result();
...
workers[i] = new WorkerThread(i, inputs[i], results[i]);
workers[i].start();
}
...
public void run() {
Result tmp = Processor.process(input);
this.result.updateFrom(tmp);
// ... where the updateFrom method copies the state of tmp into
// the Result object that was passed from the main thread.
}
Another approach is to replace Result[] in the main program with Result[][] and pass a Result[0] to the child thread that can be updated with the result object. (A light-weight holder).
However, there us an Important Gotcha when you are implementing this at a low level is that the main thread needs to call Thread.join on all of the child threads before attempting to retrieve the results. If you don't, there is a risk that the main thread will occasionally see stale values in the Result objects. The join also ensures that the main thread doesn't try to access a Result before the corresponding child thread has completed it.
The main thread will need to wait for the worker threads to complete before getting the results. One way to do this is for the main thread to wait for each worker thread to terminate before attempting to read the result. A thread terminates when its run() method completes.
For example:
for (int i = 0; i < workers.length; i++) {
worker.join(); // wait for worker thread to terminate
Result result = results[i]; // get the worker thread's result
// process the result here...
}
You still have to arrange for the worker thread's result to be inserted into the result[] array somehow. As one possibility, you could do this by passing the array and an index into each worker thread and having the worker thread assign the result before terminating.
Some typical solutions would be:
Hold the result in the worker thread's instance (be it Runnable or Thread). This is similar to the use of the Future interface.
Use a BlockingQueue that the worker threads are constructed with which they can place their result into.
Simple use the ExecutorService and Callable interfaces to get a Future which can be asked for the result.
It looks like your goal is to perform the computation in parallel, then once all results are available to the main thread, it can continue and use them.
If that's the case, implement your parallel computation as a Callable rather than a thread. Pass this collection of tasks to the invokeAll() method of an ExecutorService. This method will block until all the tasks have been completed, and then your main thread can continue.
I think I have a better solution, why don't you make your worker threads pass the result into a linkedListBlockingQueue, which is passed to them, after they are done, and your main function picks the results up from the queue like this
while(true){linkedListBlockingQueue.take();
//todo: fil in the task you want it to do
//if a specific kind of object is returned/countdownlatch is finished exit
}

When does the call() method get called in a Java Executor using Callable objects?

This is some sample code from an example. What I need to know is when call() gets called on the callable? What triggers it?
public class CallableExample {
public static class WordLengthCallable
implements Callable {
private String word;
public WordLengthCallable(String word) {
this.word = word;
}
public Integer call() {
return Integer.valueOf(word.length());
}
}
public static void main(String args[]) throws Exception {
ExecutorService pool = Executors.newFixedThreadPool(3);
Set<Future<Integer>> set = new HashSet<Future<Integer>>();
for (String word: args) {
Callable<Integer> callable = new WordLengthCallable(word);
Future<Integer> future = pool.submit(callable); //**DOES THIS CALL call()?**
set.add(future);
}
int sum = 0;
for (Future<Integer> future : set) {
sum += future.get();//**OR DOES THIS CALL call()?**
}
System.out.printf("The sum of lengths is %s%n", sum);
System.exit(sum);
}
}
Once you have submitted the callable, the executor will schedule the callable for execution. Depending on the executor this might happen directly or once a thread becomes available.
Calling get on the other hand only waits to retrieve the result of the computation.
So to be precise: Somewhere in-between submit being called and the call to get returning, the callable is called.
The entire idea of using an Executor is that you shouldn't care when exactly the method is called.
The only thing that is guaranteed in general is that the method will have executed when get() of the Future returns.
When exactly it will be called depends on which Executor you use. With the fixed thread pool you use in the example, the call() method will be called as soon as there is a free thread and no other task is in front of the given task in the queue (so as long as there are enough tasks, you'll have 3 call() method calls running at any given time in your example).
The answer to "when will a callable be schedules" lies in java.util.concurrent.ThreadPoolExecutor#execute implementation (the default)

Categories