How to synchronize the handover of array between 2 pool threads? - java

I have such scenario (this is Java pseudo code):
There is a main thread which:
1) creates an instance of an array of type C:
C[] arr = new C[LARGE];
2) creates and submits tasks which populate (by doing CPU bound operations) the arr to a pool P1:
for (int i = 0; i < populateThreadCount; i++) {
p1.submit(new PopulateTask(arr, start, end))
}
Each task populates different range of indexes in arr so at this point synchronization is not needed between threads in pool P1.
3) the main thread waits until all populate tasks are finished.
4) once the arr is populated, main thread creates and submits tasks which upload (IO bound operations) the content of arr, to a pool P2:
for (int i = 0; i < uploadThreadCount; i++) {
p2.submit(new UploadTask(arr, start, end);
}
As previously, the ranges are not overlapping, each thread has it's own range so no internal synchronization between threads in P2 pool is necessary.
In the populate and upload tasks the ranges are different as there is a different number of threads to handle each type.
Now I am thinking what is the most efficient way to synchronize it.
Using CopyOnWriteArrayList is not an option as it can be very large (millions of elements).
My initial idea was to synchronize briefly in a populate task after creating an instance of a C class and then to the same in an upload task:
C[] arr = new C[LARGE];
for (int i = 0; i < populateThreadCount; i++) {
p1.submit(new PopulateTask(arr, start, end) {
void run() {
for (int j = start; j <= end; j++) {
... do some heavy computation ...
arr[j] = new C(some_computed_data);
synchronized(arr[j]) {}
}
}
});
}
for (int i = 0; i < uploadThreadCount; i++) {
p2.submit(new UploadTask(arr, start, end) {
void run() {
for (int j = start; j <= end; j++) {
synchronized(arr[j]) {
upload(arr[j]);
}
}
}
});
}
but not sure if this is correct, especially if this empty synchronized block won't be optimized out by javac or JIT.
I cannot create the instances of C class before starting the populate tasks as for that I need the computed data.
Any ideas, if that's correct and if not a way to do it better?

You don't need to synchronize anything. The executor offers the memory visibility guarantees you need. In particular, see the concurrent package documentation:
Actions in a thread prior to the submission of a Runnable to an Executor happen-before its execution begins. Similarly for Callables submitted to an ExecutorService.
Actions taken by the asynchronous computation represented by a Future happen-before actions subsequent to the retrieval of the result via Future.get() in another thread.
So, the changes done by the tasks submitted to the first executor happen before what the main thread does after the executor has finished executing them (second rule), and what the main thread does with the array happens before the actions executed by the tasks submitted to the second executor (first rule).
Since happen-before is transitive, the tasks submitted to the second executor will see the changes made by the tasks submitted to the first one.

Related

BlockingQueue program does not exit

I was referring the concept of BlockingQue and I found one example here.
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue; /* j a v a 2s . co m*/
public class Main {
public static void main(String[] argv) throws Exception {
int capacity = 10;
BlockingQueue < Integer > queue = new ArrayBlockingQueue < Integer > (capacity);
int numWorkers = 2;
Worker[] workers = new Worker[numWorkers];
for (int i = 0; i < workers.length; i++) {
workers[i] = new Worker(queue);
workers[i].start();
}
for (int i = 0; i < 10; i++) {
queue.put(i);
}
}
}
class Worker extends Thread {
BlockingQueue < Integer > q;
Worker(BlockingQueue < Integer > q) {
this.q = q;
}
public void run() {
try {
while (true) {
Integer x = q.take();
if (x == null) {
break;
}
System.out.println(x);
}
} catch (InterruptedException e) {}
}
}
In the example, they have used only one thread which is a Worker thread.
What I understood about BlockingQue is that it is an alternate solution to Producer-Consumer pattern.
So we need two threads to work on. Hence I have doubts/questions.
Below are my questions.
have they used main thread as another thread?
When I run the application, the program does not get exited. I did not understand the reason why the main program does not exit?
In the example code that you are referring , you have one Producer (Main Thread) and two Consumers (Worker Threads).
In Producer - Consumer problem, its not necessary to have only one Producer and only one Consumer - you can have multiple producers and multiple consumers. Their relative number is usually decided about who is doing more complex and time consuming tasks.
Answer 1: main thread is producer thread since it is being used to put items to BlockingQueue, queue.put(i)
Answer 2: your main thread exits after putting ten elements to queue but your worker thread keeps waiting for elements ( even after consuming ten elements ) because q.take() is a blocking method i.e. it waits for more elements to be put to queue (when queue is empty)
Solution : You need to put two EOF elements / Objects (END OF FILE) to queue and do a check like you did , if (x == null). Try putting two extra nulls in queue so when your worker/consumer threads find it, they will terminate. Currently, your condition if (x == null) is never met.
Answer 1. No they have not used main thread for anything else. Main thread exit perfectly.
Answer 2. JVM does not exit until all the non-daemon thread ends. (Source: http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html)
If you want the JVM to exit once the main thread finishes make your Worker threads to daemon thread by adding workers[i].setDaemon(true); inside your for loop.
The reason why your non-daemon threads doesn't exist is you have Integer x = q.take(); inside while loop on Worker's run method. thus those Worker threads are forever waiting for new Integers to be put on the queue.
Suggestions: You can use Eclipse Java IDE to debug and see whats actually going on each thread

Java Thread Pool Timing Issue

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.

Invoking different methods on threads

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.

Parallel threading in Java

Ok, so I'm trying to find the maximum element of a 2D array. I will have a method that accepts the 2darray as a parameter and finds the maximum. It needs to find the maximum element of each row as a separate thread so that the threads run parrallel, then join each thread, and finding the max of those to get the maximum of the entire 2d array. Now the problem I'm having is that run() does not return any value...How then am i supposed to access the value that has been modified. for example
public static int maxof2darray(long[][] input){
ArrayList<Thread> threads = new ArrayList<Thread>();
long[]rowArray;
for(int i=0; i<input.length; i++){
rowArray = input[i];
teste r1 = new teste(rowArray,max);
threads.add(new Thread(r1));
}
for ( Thread x : threads )
{
x.start();
}
try {
for ( Thread x : threads)
{
x.join();
}
}
as you can see it creates an arraylist of thread objects. Then takes each row and calls the run() function that finds the maximum of that row...the problem is run() does not return any value...How then can i possibly access the maximum of that row?
The Future API should do what you need.
A Future represents the result of an
asynchronous computation. Methods are
provided to check if the computation
is complete, to wait for its
completion, and to retrieve the result
of the computation. The result can
only be retrieved using method get
when the computation has completed,
blocking if necessary until it is
ready. Cancellation is performed by
the cancel method. Additional methods
are provided to determine if the task
completed normally or was cancelled.
Once a computation has completed, the
computation cannot be cancelled. If
you would like to use a Future for the
sake of cancellability but not provide
a usable result, you can declare types
of the form Future and return null
as a result of the underlying task.
I think this is not proper way for starting and joining the threads. You should use Thread Pool instead.
Following is a sample of code that demonstrates Thread Pool.
ExecutorService workers = Executors.newFixedThreadPool(10);
for(int i=0; i<input.length; i++) {
Teste task = new Teste(rowArray,max);
workers.execute(task);
}
workers.shutdown();
while(!workers.isTerminated()) {
try {
Thread.sleep(10000);
} catch (InterruptedException exception) {
}
System.out.println("waiting for submitted task to finish operation");
}
Hope this help.
Unless the array is fairly large it will be faster to do the search in one thread. However say the size is 1000s or more I suggest you use the ExecutionService which is a simple way to manage tasks.
However, the simplest change is to store the result in an AtomicLong, that way your Runnables don't need to return a result.
You can add a new field to your "teste" class that holds the max row. The main thread stops at x.join(), so after that line to can refer to that field and get the max value.
.
.
.
int max=0;
for ( Thread x : threads)
{
x.join();
max=x.getMax();
}
.
.
.

How to join one thread with other in java?

I have one main thread that starts 10 other threads. I want that the main thread will be finished only after all other threads stopped. So should I call join() on other 10 threads before starting or after starting them. For instance:
// in the main() method of Main thread
Thread [] threads = new Thread[10];
for(int i = 0; i < 10; i++) {
// ParserThread() is a runnable thread
threads[i] = new Thread(new ParserThread());
threads[i].join();
threads[i].start();
}
System.out.println("All threads have been finished"); // line no. 9
So as in the above example, should i call join() before start() or after start().
Will the control returns to line no. 9 only after all the threads have finished.
When the run method of any thread has been executed, then will that thread die or remain alive. If it will, the how to die all the threads when their run method has finished means when the control returns to line no. 9
Calling join() on a thread only makes sense after the thread is started. The caller of join() will stop and wait until the other thread finishes what it's doing. So you may want to do this:
// in the main() method of Main thread
Thread [] threads = new Thread[10];
for(int i = 0; i < 10; i++) {
// ParserThread() is a runnable thread
threads[i] = new Thread(new ParserThread());
threads[i].start();
}
System.out.println("All threads have been started");
for(int i = 0; i < 10; i++) {
threads[i].join();
}
System.out.println("All threads have been finished");
I recommend against using the low-level Thread constructs like join(), and instead using the higher-level stuff in java.util.concurrent, like CyclicBarrier:
A synchronization aid that allows a
set of threads to all wait for each
other to reach a common barrier point.
CyclicBarriers are useful in programs
involving a fixed sized party of
threads that must occasionally wait
for each other. The barrier is called
cyclic because it can be re-used after
the waiting threads are released.
The usage is much more obvious that Thread.join(), and much less prone to weird bugs.
Instead of writing your own code, you code use a ThreadPoolExecutor to do what you need:
ThreadPoolExecutor executor = new ThreadPoolExecutor(0, 10, 2, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
for (int i = 0; i < 10; i++)
executor.execute(new ParserThread());
try {
executor.shutdown();
executor.awaitTermination(10, TimeUnit.MINUTES);
} catch (final InterruptedException e) {
// handle
}
This way, you could easily use less threads to do more tasks if you wish - without changing the code.
you should first start all the thread, then start joining them. Join will return direct if called before the thread is start.
Case can be that you want to join group of threads. See javadoc for
http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorCompletionService.html
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);
}
}
For trivial scenarios (one thread), Thread.join() is enough.

Categories

Resources