How to create multiple threads inside of a for loop - java

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.

Related

How to print some messages before and after thread iteration?

I asked yesterday about thread synchronization in this post.
Finally, synchronization issue is solved, but I have to print before/after threads iteration.
The code is below, it's just iteration.
for(int i=0; i<5; i++) {
CarSensors=
new Thread[]{
new Thread(frontCarSensor),
new Thread(leftRightCarSensor),
new Thread(LaneSensor),
new Thread(SignalSensor),
new Thread(PedestrianSensor),
new Thread(ObjectSensor)
};
for(Thread t:CarSensors) t.start();
}
I tried to print message "Car sensor checking..." before for loop and \n after for loop but it is mixed in other messages because main thread is also thread.
How can I fix it?
+Some important information
I cannot use join or completablefuture. I have to use notify() or wait()
My result expectation is below.
print a message "start"
main program execution
print a message "end"
print a message "start"
main program execution
print a message "end"
print a message "start"
main program execution
print a message "end"
It continues for a 5 times.
"main program" means 6 threads of ~sensor object.
+Request for Sensor class
public abstract class Sensor implements Runnable {
protected Random random;
protected HashMap<String,String> message;
protected final static Object lock=new Object();
protected String[] event;
protected Sensor(){
random=new Random();
message=new HashMap<String,String>();
}
public abstract void Direction();
}
I would probably refrain from using Thread directly in Java unless I am writing a concurrency building block. Also, threads are very expensive, compared to most other things you can do programmatically, so when possible, dynamic thread creation (especially in loops) should be avoided.
In the subject case a solution may be to use the functionality of CompletableFuture and Executors framework (basic example below).
The CompletableFuture allows registering completion hooks, so any sort of telemetry can be wrapped around the main logic without touching the latter.
To prevent message overlapping delegate printing to a single thread executor and have them ordered by timestamp, by the car ID, or anything else appropriate.
import static java.util.concurrent.CompletableFuture.runAsync;
// You can use JDK Executors, Guava Executors,
// or write your own taking the concurrency consideration
// away from the business logic
final Executor executor = Executors.newFixedThreadPool(N);
CompletableFuture collector = CompletableFuture.completed((Void)null);
for (int i = 0; i < 5; ++i) {
collector = CompletableFuture.allOf(
collector,
runAsync(frontCarSensor, executor),
runAsync(leftRightCarSensor, executor),
runAsync(LaneSensor, executor),
runAsync(SignalSensor, executor),
runAsync(PedestrianSensor, executor),
runAsync(ObjectSensor, executor)).join();
}
collector.join();
You need to add the printing inside the code for CarSensoer
If each of those parameters in Thread constructor is Runnable class, you can add print statements in run() method
public abstract class Sensor implements Runnable {
//some other code
}
public class LaneSensor extends Sensor {
#Override
public void run() {
System.out.println("Pre Execution thread " + Thread.currentThread().getName());
// print
// execution code
// print
System.out.println("Post Execution thread " + Thread.currentThread().getName());
}
}

Java 8 Concurrency Simplest Canonical Form for Basic Task

I have two questions:
1. What is the simplest canonical form for running a Callable as a task in Java 8, capturing and processing the result?
2. In the example below, what is the best/simplest/clearest way to hold the main process open until all the tasks have completed?
Here's the example I have so far -- is this the best approach in Java 8 or is there something more basic?
import java.util.*;
import java.util.concurrent.*;
import java.util.function.*;
public class SimpleTask implements Supplier<String> {
private SplittableRandom rand = new SplittableRandom();
final int id;
SimpleTask(int id) { this.id = id; }
#Override
public String get() {
try {
TimeUnit.MILLISECONDS.sleep(rand.nextInt(50, 300));
} catch(InterruptedException e) {
System.err.println("Interrupted");
}
return "Completed " + id + " on " +
Thread.currentThread().getName();
}
public static void main(String[] args) throws Exception {
for(int i = 0; i < 10; i++)
CompletableFuture.supplyAsync(new SimpleTask(i))
.thenAccept(System.out::println);
System.in.read(); // Or else program ends too soon
}
}
Is there a simpler and clearer Java-8 way to do this? And how do I eliminate the System.in.read() in favor of a better approach?
The canonical way to wait for the completion of multiple CompletableFuture instance is to create a new one depending on all of them via CompletableFuture.allOf. You can use this new future to wait for its completion or schedule new follow-up actions just like with any other CompletableFuture:
CompletableFuture.allOf(
IntStream.range(0,10).mapToObj(SimpleTask::new)
.map(s -> CompletableFuture.supplyAsync(s).thenAccept(System.out::println))
.toArray(CompletableFuture<?>[]::new)
).join();
Of course, it always gets simpler if you forego assigning a unique id to each task. Since your first question was about Callable, I’ll demonstrate how you can easily submit multiple similar tasks as Callables via an ExecutorService:
ExecutorService pool = Executors.newCachedThreadPool();
pool.invokeAll(Collections.nCopies(10, () -> {
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(
ThreadLocalRandom.current().nextInt(50, 300)));
final String s = "Completed on "+Thread.currentThread().getName();
System.out.println(s);
return s;
}));
pool.shutdown();
The executor service returned by Executors.newCachedThreadPool() is unshared and won’t stay alive, even if you forget to invoke shutDown(), but it can take up to one minute before all threads are terminated then.
Since your first question literally was: “What is the simplest canonical form for running a Callable as a task in Java 8, capturing and processing the result?”, the answer might be that the simplest form still is invoking it’s call() method directly, e.g.
Callable<String> c = () -> {
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(
ThreadLocalRandom.current().nextInt(50, 300)));
return "Completed on "+Thread.currentThread().getName();
};
String result = c.call();
System.out.println(result);
There’s no simpler way…
Consider collecting the futures into a list. Then you can use join() on each future to await their completion in the current thread:
List<CompletableFuture<Void>> futures = IntStream.range(0,10)
.mapToObj(id -> supplyAsync(new SimpleTask(id)).thenAccept(System.out::println))
.collect(toList());
futures.forEach(CompletableFuture::join);

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.

How can I make sure a threadpool is finished?

The setup:
I am in the process of changing the way a program works under the hood. In the current version works like this:
public void threadWork( List<MyCallable> workQueue )
{
ExecutorService pool = Executors.newFixedThreadPool(someConst);
List<Future<myOutput>> returnValues = new ArrayList<Future<myOutput>>();
List<myOutput> finishedStuff = new ArrayList<myOutput>();
for( int i = 0; i < workQueue.size(); i++ )
{
returnValues.add( pool.submit( workQueue.get(i) ) );
}
while( !returnValues.isEmpty() )
{
try
{
// Future.get() waits for a value from the callable
finishedStuff.add( returnValues.remove(0).get(0) );
}
catch(Throwable iknowthisisbaditisjustanexample){}
}
doLotsOfThings(finsihedStuff);
}
But the new system is going to use a private inner Runnable to call a synchronized method that writes the data into a global variable. My basic setup is:
public void threadReports( List<String> workQueue )
{
ExecutorService pool = Executors.newFixedThreadPool(someConst);
List<MyRunnable> runnables = new ArrayList<MyRunnable>()
for ( int i = 0; i < modules.size(); i++ )
{
runnables.add( new MyRunnable( workQueue.get(i) );
pool.submit(threads.get(i));
}
while( !runnables.isEmpty() )
{
try
{
runnables.remove(0).wait(); // I realized that this wouldn't work
}
catch(Throwable iknowthisisbaditisjustanexample){}
}
doLotsOfThings(finsihedStuff); // finishedStuff is the global the Runnables write to
}
If you read my comment in the try of the second piece of code you will notice that I don't know how to use wait(). I had thought it was basically like thread.join() but after reading the documentation I see it is not.
I'm okay with changing some structure as needed, but the basic system of taking work, using runnables, having the runnables write to a global variable, and using a threadpool are requirements.
The Question
How can I wait for the threadpool to be completely finished before I doLotsOfThings()?
You should call ExecutorService.shutdown() and then ExecutorService.awaitTermination.
...
pool.shutdown();
if (pool.awaitTermination(<long>,<TimeUnit>)) {
// finished before timeout
doLotsOfThings(finsihedStuff);
} else {
// Timeout occured.
}
Try this:
pool.shutdown();
pool.awaitTermination(WHATEVER_TIMEOUT, TimeUnit.SECONDS);
Have you considered using the Fork/Join framework that is now included in Java 7. If you do not want to use Java 7 yet you can get the jar for it here.
public void threadReports( List<String> workQueue )
{
ExecutorService pool = Executors.newFixedThreadPool(someConst);
Set<Future<?>> futures = new HashSet<Future<?>>();
for ( int i = 0; i < modules.size(); i++ )
{
futures.add(pool.submit(threads.get(i)));
}
while( !futures.isEmpty() )
{
Set<Future<?>> removed = new Set<Future<?>>();
for(Future<?> f : futures) {
f.get(100, TimeUnit.MILLISECONDS);
if(f.isDone()) removed.add(f);
}
for(Future<?> f : removed) futures.remove(f);
}
doLotsOfThings(finsihedStuff); // finishedStuff is the global the Runnables write to
}
shutdownis a lifecycle method of the ExecutorService and renders the executor unusable after the call. Creating and destroying ThreadPools in a method is as bad as creating/destroying threads: it pretty much defeats the purpose of using threadpool, which is to reduce the overhead of thread creation by enabling transparent reuse.
If possible, you should maintain your ExecutorService lifecycle in sync with your application. - create when first needed, shutdown when your app is closing down.
To achieve your goal of executing a bunch of tasks and waiting for them, the ExecutorService provides the method invokeAll(Collection<? extends Callable<T>> tasks) (and the version with timeout if you want to wait a specific period of time.)
Using this method and some of the points mentioned above, the code in question becomes:
public void threadReports( List<String> workQueue ) {
List<MyRunnable> runnables = new ArrayList<MyRunnable>(workQueue.size());
for (String work:workQueue) {
runnables.add(new MyRunnable(work));
}
// Executor is obtained from some applicationContext that takes care of lifecycle mgnt
// invokeAll(...) will block and return when all callables are executed
List<Future<MyRunnable>> results = applicationContext.getExecutor().invokeAll(runnables);
// I wouldn't use a global variable unless you have a VERY GOOD reason for that.
// b/c all the threads of the pool doing work will be contending for the lock on that variable.
// doLotsOfThings(finishedStuff);
// Note that the List of Futures holds the individual results of each execution.
// That said, the preferred way to harvest your results would be:
doLotsOfThings(results);
}
PS: Not sure why threadReports is void. It could/should return the calculation of doLotsOfThings to achieve a more functional design.

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