I am new to Multithreading and I am trying make my program faster using ExecutorService. Below is y implementation but, my program is still not working fast. Can you please look at my code and advise?
It basically reads the list of email addresses and stores in the ArrayList. I use the ExecutorService and loop through the ArrayList and call a Callable class does some processing and returns a Boolean.
ArrayList<String> emailAddressList = new ArrayList<>();
ExecutorService executor = Executors.newFixedThreadPool(7);
for (int i = 0; i < emailAddressList.size(); i++) {
Future<Boolean> resultFromThread = executor.submit(new Verify(emailAddressList.get(i)));
bufferedWriter.write(emailAddressList.get(i) + "|" + resultFromThread.get());
bufferedWriter.newLine();
}
executor.shutdown();
executor.awaitTermination(3, TimeUnit.SECONDS);
===========================================================================
public class Verify implements Callable<Boolean> {
private String email;
public Verify(String email) {
this.email = email;
}
#Override
public Boolean call() throws Exception {
Boolean result = false;
try {
result = Validator2.isAddressValid(email);
} catch (Exception e) {
}
return result;
}
}
In each iteration of the loop, two actions are performed:
A Callable is scheduled to run with the Executor
Immediately after that - yet before another task is scheduled - the code waits for the Executor to complete the Callable just submitted.
That way, all Callables are still executed in a serial fashion (we wait to complete one before we submit another), rather than executing them in parallel.
A simple solution might be to submit all callables for execution first. Then, in a separate loop, the wait for them to complete and to process the results. That way, the performance shall improve because of parallel processing of the Callables.
Example:
List<Future<Boolean>> futures ... ;
for (int i = 0; i < emailAddressList.size(); i++) {
futures.add(executor.submit(new Verify(emailAddressList.get(i))));
}
for (int i = 0; i < emailAddressList.size(); i++)
bufferedWriter.write(emailAddressList.get(i) + "|" + futures.get(i).get());
bufferedWriter.newLine();
}
Note that this code waits for the Callables to complete in the order they were submitted to the Executor. This may not necesarily be the case. If the order of the adresses in the resulting writer is not important, one may consider a completely asychronous processing. In Java 8, this can be achieved e.g using the CompleteableFuture API.
You have effectively made your code synchronous and single-threaded without offering any advantage to using a threaded executor. When calling resultFromThread.get(), it will block the main thread and will prevent the next loop iteration that submits the next Task to execute from running until the previous one completes. If you want the submitted Verify tasks to run concurrently, you should submit all of the tasks first in one loop appended to a List<Future<Boolean>>. Then, in another loop, you can iterate through each of those and then call .get(), such that the main thread will await completion of all executions, but won't stop the 7 other threads from executing concurrently.
Related
I have a set of jobs which I am submitting using executor framework and Future. Let's say that I have 100 futures. As of now, I am using Future.get and using the output for subsequent processing. However for further tuning, I want to change the flow as below:
iterate through the set of future tasks and start consuming the result as soon as a future task is complete. I am reading the API doc to understand what might be a good way to accomplish this but reaching out to see if there is a better way to accomplish what I am looking for.
Here is the sample code:
public class ImplCallable implements Callable<String> {
int timeOut;
ImplCallable(int timeOut) {
this.timeOut=timeOut;
}
public String call() throws Exception {
Thread.sleep(timeOut);
return Thread.currentThread().getName();
}
}
and the main class:
public class MainProg {
public static void main(String...args) throws Exception {
long startTimeInMillis = System.currentTimeMillis();
ImplCallable callable1 = new ImplCallable(1000);
ImplCallable callable2 = new ImplCallable(2000);
ExecutorService service = Executors.newFixedThreadPool(4);
Future<String> task1 = service.submit(callable1);
Future<String> task2 = service.submit(callable2);
List<Future<String>> futureList = new ArrayList();
futureList.add(task1);
futureList.add(task2);
String retVal;
for(Future<String> task:futureList) {
retVal = task.get();
//do something with the retVal
}
long endTimeInMillis = System.currentTimeMillis();
System.out.println("time taken by code - " + (endTimeInMillis-startTimeInMillis) + "-ms");
}
}
Basically I don't want to use Future.get() and wait for its completion. I want to know if either of the task is complete and use the result as soon as its done.
There are many ways do this so, without a concrete example, you won't get a concrete answer. Likely want to look at CompletableFuture which has many methods for defining follow-on work, combining work, splitting work etc.
Future<String> f = CompletableFuture.supplyAsync(() -> "INITIAL WORK")
.thenApply(String::toLowerCase) // Do some more work
.thenAccept(queue::add); // put results onto a queue something is reading from
f.join();
// Batch complete
I hope you are using Java 8 or later version.
Whenever you mention "as soon as a future task is complete", you want to use CompletableFuture and its .thenApply() method, as #drekbour suggests.
Then you have multiple threads running different tasks in non-determenistic sequence. But at the end you want to get all the results in the single (Main) thread. To achieve it, you can use CompletableFuture.allOf method, .join() it - and then iterate over all the (already completed) future results without waiting.
I have written a simple program, that is intended to start a few threads. The threads should then pick a integer n from an integer array, use it to wait n and return the time t the thread waited back into an array for the results.
If one thread finishes it's task, it should pick the next one, that has not yet being assigned to another thread.
Of course: The order in the arrays has to be maintained, so that integers and results match.
My code runs smoothly as far I see.
However I use one line of code block I find in particular unsatisfying and hope there is a good way to fix this without changing too much:
while(Thread.activeCount() != 1); // first evil line
I kinda abuse this line to make sure all my threads finish getting all the tasks done, before I access my array with the results. I want to do that to prevent ill values, like 0.0, Null Pointer Exception... etc. (in short anything that would make an application with an actual use crash)
Any sort of constructive help is appreciated. I am also not sure, if my code still runs smoothly for very very long arrays of tasks for the threads, for example the results no longer match the order of the integer.
Any constructive help is appreciated.
First class:
public class ThreadArrayWriterTest {
int[] repitions;
int len = 0;
double[] timeConsumed;
public boolean finished() {
synchronized (repitions) {
return len <= 0;
}
}
public ThreadArrayWriterTest(int[] repitions) {
this.repitions = repitions;
this.len = repitions.length;
timeConsumed = new double[this.len];
}
public double[] returnTimes(int[] repititions, int numOfThreads, TimeConsumer timeConsumer) {
for (int i = 0; i < numOfThreads; i++) {
new Thread() {
public void run() {
while (!finished()) {
len--;
timeConsumed[len] = timeConsumer.returnTimeConsumed(repititions[len]);
}
}
}.start();
}
while (Thread.activeCount() != 1) // first evil line
;
return timeConsumed;
}
public static void main(String[] args) {
long begin = System.currentTimeMillis();
int[] repitions = { 3, 1, 3, 1, 2, 1, 3, 3, 3 };
int numberOfThreads = 10;
ThreadArrayWriterTest t = new ThreadArrayWriterTest(repitions);
double[] times = t.returnTimes(repitions, numberOfThreads, new TimeConsumer());
for (double d : times) {
System.out.println(d);
}
long end = System.currentTimeMillis();
System.out.println("Total time of execution: " + (end - begin));
}
}
Second class:
public class TimeConsumer {
double returnTimeConsumed(int repitions) {
long before = System.currentTimeMillis();
for (int i = 0; i < repitions; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
long after = System.currentTimeMillis();
double ret = after - before;
System.out.println("It takes: " + ret + "ms" + " for " + repitions + " runs through the for-loop");
return ret;
}
}
The easiest way to wait for all threads to complete is to keep a Collection of them and then call Thread.join() on each one in turn.
In addition to .join() you can use ExecutorService to manage pools of threads,
An Executor that provides methods to manage termination and methods
that can produce a Future for tracking progress of one or more
asynchronous tasks.
An ExecutorService can be shut down, which will cause it to reject new
tasks. Two different methods are provided for shutting down an
ExecutorService. The shutdown() method will allow previously submitted
tasks to execute before terminating, while the shutdownNow() method
prevents waiting tasks from starting and attempts to stop currently
executing tasks. Upon termination, an executor has no tasks actively
executing, no tasks awaiting execution, and no new tasks can be
submitted. An unused ExecutorService should be shut down to allow
reclamation of its resources.
Method submit extends base method Executor.execute(Runnable) by
creating and returning a Future that can be used to cancel execution
and/or wait for completion. Methods invokeAny and invokeAll perform
the most commonly useful forms of bulk execution, executing a
collection of tasks and then waiting for at least one, or all, to
complete.
ExecutorService executorService = Executors.newFixedThreadPool(maximumNumberOfThreads);
CompletionService completionService = new ExecutorCompletionService(executorService);
for (int i = 0; i < numberOfTasks; ++i) {
completionService.take();
}
executorService.shutdown();
Plus take a look at ThreadPoolExecutor
Since java provides more advanced threading API with concurrent package, You should have look into ExecutorService, which simplifies thread management mechanism.
Simple to solution to your problem.
Use Executors API to create thread pool
static ExecutorService newFixedThreadPool(int nThreads)
Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue.
Use invokeAll to wait for all tasks to complete.
Sample code:
ExecutorService service = Executors.newFixedThreadPool(10);
List<MyCallable> futureList = new ArrayList<MyCallable>();
for ( int i=0; i<12; i++){
MyCallable myCallable = new MyCallable((long)i);
futureList.add(myCallable);
}
System.out.println("Start");
try{
List<Future<Long>> futures = service.invokeAll(futureList);
for(Future<Long> future : futures){
try{
System.out.println("future.isDone = " + future.isDone());
System.out.println("future: call ="+future.get());
}
catch(Exception err1){
err1.printStackTrace();
}
}
}catch(Exception err){
err.printStackTrace();
}
service.shutdown();
Refer to this related SE question for more details on achieving the same:
wait until all threads finish their work in java
I'm trying to use a thread pool to execute some code, however I'm having some trouble getting it to run without errors.
Here is my current structure:
while (!(queue.IsEmpty()))
{
currentItem= queue.GetNextItem();
for (int i = 0; i < currentItem.destinations.GetNoOfItems(); i++) //for each neighbor of currentItem
{
threadPool.submit(new NeighbourThread(currentItem, allVertices, routetype, pqOpen, i, endLocation));
}
//threadPool.shutdown();
}
NeighbourThread class:
public class NeighbourThread implements Runnable {
Vertex tempVertex, endLocation;
VertexHashMap allVertices;
int routetype, i;
PriorityQueue pqOpen;
public NeighbourThread(Vertex tempVertex, VertexHashMap allVertices, int routetype, PriorityQueue pqOpen, int i, Vertex endLocation)
{
...variables
}
#Override
public void run() {
...execution code
}
}
My idea is that it will create the amount of threads required based on currentItem.destinations.GetNoOfItems()(as it reuses threads, I'm assuming if it reaches the limit on thread creation it will wait for a thread to finish execution and reuse it).
Once the threads have been allocated, it will submit each runnable to the thread and start it.
However I need my program to wait for all threads to finish execution before it loops back to the while loop.
After reading the documentation on .shutdown(), I think that stops any future use of the threadpool, which I'm guessing is why I get this error:
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask#3d4eac69 rejected from java.util.concurrent.ThreadPoolExecutor#42a57993[Shutting down, pool size = 3, active threads = 1, queued tasks = 0, completed tasks = 3]
I'm trying to improve execution time on my program and as I'm currently doing over 1.5 million invocations of what will be in the run() method, I feel this will help.
So is there anyway to get the program to wait until the threads have finished before continuing with the while loop?
The easiest solution is to use the Futures to notify you when they have completed. Unfortunately, Java does not support listenable Futures out of the box, but you can use the Guava library to supplement you here.
Guava adds the ListeneableFuture, which you can make using the Futures utility class:
ListeningExecutorService executor = MoreExecutors.listeningDecorator(threadPool);
// Collect the futures as you add them to the threadpool
List<ListenableFuture<?>> futures = new ArrayList<>();
while (! queue.IsEmpty())
{
currentItem = queue.GetNextItem();
for (int i = 0; i < currentItem.destinations.GetNoOfItems(); i++)
{
// NeighbourThread should be a Runnable and not a Thread!
futures.add(executor.submit(new NeighbourThread(currentItem, allVertices, routetype, pqOpen, i, endLocation)));
}
}
// Get notified when they're all done (doesn't imply success!)
Futures.allAsList(futures)).addListener(new Runnable() {
// When this callback is executed, then everything has finished
}, MoreExecutors.directExecutor());
Alternatively, you could do this with a CountdownLatch if you know how many items you need to run upfront.
I have one "Runnable" threads which is initiating few "Callable" threads and I want to display results when all above threads has finished their jobs.
What is the best way to do it?
My code is as follows
Connector.java (Starting Runnable Thread)
public class Connector {
private static void anyFileConnector() {
// Starting searching Thread
ExecutorService executor = Executors.newFixedThreadPool(100);
executor.submit(traverse, executor);
//HERE I WANT MY ALL SEARCH RESULTS/OUTPUT : CURRENTLY IT IS STARTING OTHER THREADS AND NOT SHOWING ME ANY RESULTS BECAUSE NONE OF THEM WAS FINISHED.(IN CONSOLE, I WAS ABLE TO SEE RESULTS FROM ALL THE THREADS
setSearchResult(traverse.getResult());
executor.shutdown();
}
}
Traverse.java (Runnable Thread)
I am using ExecutorCompletionService to handle it...but it didn't create any difference.
:(
public class Traverse implements Runnable {
public void run() {
ExecutorService executor = Executors.newFixedThreadPool(100);
ExecutorCompletionService<List<ResultBean>> taskCompletionService =
new ExecutorCompletionService<List<ResultBean>>(executor);
try (DirectoryStream<Path> stream = Files
.newDirectoryStream(dir)) {
Search newSearch = new Search();
taskCompletionService.submit(newSearch);
}
list.addAll(taskCompletionService.take().get());
}
}
Search.java (Callable Thread)
public class Search implements Callable<List<ResultBean>> {
public List<ResultBean> call() {
synchronized (Search.class) {
// It will return results
return this.search();
}
}
}
Go for CyclicBarrier and you will be able to achieve this.
A cyclic barrier will perform a task as soon as all the threads are done with their work, this is where you can print the en result.
Check this lik for working of CyclicBarrier : http://javarevisited.blogspot.com/2012/07/cyclicbarrier-example-java-5-concurrency-tutorial.html
Easy - all the Callables will return Future objects which you can used to wait and get the result by calling Future.get() in a blocking wait way. So your problem is just a for loop waiting for each future on the callables blockingly.
After that, just aggregate the results to return to client.
The submit method of executor service can return a list of Future objects. What you can do for your case is call isDone() method of these Future objects in a while loop.
Whenever, any future task gets completed this method will return true. You can now call get() method on this to get the value returned by this task. In this way you could get hold of all the future task values without having to wait for any particular task to get complete (since your first future task could have the longest completion time)
I have a main process main. It creates 10 threads (say) and then what i want to do is the following:
while(required){
Thread t= new Thread(new ClassImplementingRunnable());
t.start();
counter++;
}
Now i have the list of these threads, and for each thread i want to do a set of process, same for all, hence i put that implementation in the run method of ClassImplementingRunnable.
Now after the threads have done their execution, i wan to wait for all of them to stop, and then evoke them again, but this time i want to do them serially not in parallel.
for this I join each thread, to wait for them to finish execution but after that i am not sure how to evoke them again and run that piece of code serially.
Can i do something like
for(each thread){
t.reevoke(); //how can i do that.
t.doThis(); // Also where does `dothis()` go, given that my ClassImplementingRunnable is an inner class.
}
Also, i want to use the same thread, i.e. i want the to continue from where they left off, but in a serial manner.
I am not sure how to go about the last piece of pseudo code.
Kindly help.
Working with with java.
You can't restart a thread.
What you could do is use the java.util.concurrent package to wait for the threads to finish and rerun you runnables in the main thread to run them sequentially - by putting your runnables in a list, you can access them during the sequential run.
ExecutorService executor = Executors.newFixedThreadPool(10);
List<Runnable> runnables = new ArrayList<Runnable> ();
for (int i = 0; i < 10; i++) {
Runnable r = new ClassImplementingRunnable();
runnables.add(r);
executor.submit(r);
}
executor.shutdown();
//wait until all tasks are finished
executor.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
//re run the tasks sequentially
for (ClassImplementingRunnable r : runnables) {
//the method below can access some variable in
//your ClassImplementingRunnable object, that was
//set during the first parallel run
r.doSomethingElse();
}
If you want serial execution, just use
for (int i = 0; i < 10; i++)
new ClassImplementingRunnable().run();
all the tasks will run in the same thread, one after the other. This is the cleanest way to achieve what you want.
Update
After your comment it is clear that you in fact don't want to run the same tasks again, but to print the results that were calculated by them. This would be even simpler:
add the ClassImplementingRunnable instances into a list of tasks;
run each task in its own thread;
join all the threads;
write a for loop that prints the results from each ClassImplementingRunnable instance.
You already have 2 and 3.
I guess you want something like
ExecutorCompletionService
Example copied from Java doc.
Usage Examples. Suppose you have a set of solvers for a certain problem, each returning a value of some type Result, and would like to run them concurrently, processing the results of each of them that return a non-null value, in some method use(Result r). You could write this as:
void solve(Executor e,
Collection<Callable<Result>> solvers)
throws InterruptedException, ExecutionException {
CompletionService<Result> ecs
= new ExecutorCompletionService<Result>(e);
for (Callable<Result> s : solvers)
ecs.submit(s);
int n = solvers.size();
for (int i = 0; i < n; ++i) {
Result r = ecs.take().get();
if (r != null)
use(r);
}
}
Although there are some great answers here, I'm not sure your initial questions have been answered.
Now after the threads have done their execution, i wan to wait for all of them to stop, and then evoke them again, but this time i want to do them serially not in parallel.
You are confusing the running thread from it's object. It is a very common pattern (although usually made better with the ExecutiveService classes) to do something like the following:
List<ClassExtendingThread> threads = new ArrayList<ClassExtendingThread>();
// create your list of objects
for (int i = 0; i < 10; i++) {
ClassExtendingThread thread = new ClassExtendingThread(...);
thread.start();
threads.add(thread);
}
for (ClassExtendingThread thread : threads) {
// now wait for each of them to finish in turn
thread.join();
// call some method on them to get their results
thread.doThis();
}
Notice that I changed your class to extending Thread. It is usually better to implement Runnable like you did but if you are going to be joining and calling back to the objects, extending Thread makes the code easier.
So you create your object instances, start them as threads, and then join() with them which both waits for them to finish and synchronizes their memory. Once you join() with the thread, you can call any of the methods on your objects that you'd like. That doesn't "re-evoke" the thread at all. It is just accessing the fields inside of your objects. If you try to do this while the thread is running then you need to worry about synchronization.