Reputation: 8395
I am very new to Java Multithreading . Trying to learn countdownlatch and executor in Java threading and implemented the following code-
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecutorBasicFramework {
class MyThread extends Thread{
int iCount ; String name;
CountDownLatch latch;
public MyThread(int iCount, String name, CountDownLatch latch) {
super();
this.iCount = iCount;
this.name = name;
this.latch = latch;
}
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println(name+" Printing .... "+ ++iCount+" L "+latch.getCount());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
latch.countDown();
}
}
public ExecutorBasicFramework() {
createThread();
}
private void createThread() {
ExecutorService exec = Executors.newFixedThreadPool(10);
CountDownLatch latch = new CountDownLatch(10);
for(int i=0;i<10;i++){
MyThread thread = new MyThread(i*10, ""+i,latch);
exec.execute(thread);
try {
latch.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
exec.shutdownNow();
}
public static void main(String[] args) {
new ExecutorBasicFramework();
}
}
The output coming is as -
0 Printing .... 1 L 10
0 Printing .... 2 L 10
0 Printing .... 3 L 10
0 Printing .... 4 L 10
0 Printing .... 5 L 10
0 Printing .... 6 L 10
0 Printing .... 7 L 10
0 Printing .... 8 L 10
0 Printing .... 9 L 10
0 Printing .... 10 L 10
and then the flow is like keep on waiting. My expected output is like above but after printing 0 , it should print similar output for 1 till 9 and then the program should be stopped.
I think the countdownlatch is waiting and waiting and its not going to increment the next counter of executor. So I am unable to get the expected output. I am expecting output like -
0 Printing .... 1 L 10
0 Printing .... 2 L 10
0 Printing .... 3 L 10
0 Printing .... 4 L 10
0 Printing .... 5 L 10
0 Printing .... 6 L 10
0 Printing .... 7 L 10
0 Printing .... 8 L 10
0 Printing .... 9 L 10
0 Printing .... 10 L 10
1 Printing .... 11 L 9
1 Printing .... 12 L 9
1 Printing .... 13 L 9
1 Printing .... 14 L 9
1 Printing .... 15 L 9
1 Printing .... 16 L 9
1 Printing .... 17 L 9
1 Printing .... 18 L 9
1 Printing .... 19 L 9
1 Printing .... 20 L 9
and So on ...
2 Printing .... 21 L 8
2 Printing .... 22 L 8
2 Printing .... 23 L 8
with each decrement counter of latch , the next thread is pool must execute a count till 10. and then again it must decrease the latch counter and again the process repeats till the Thread 9 completes the same
Please suggest some input .
Upvotes: 0
Views: 715
Reputation: 8395
Thanks all for inputs.
I found one more easy solution to get what I expected.
I just used Executors.newSingleThreadExecutor();
as it already ensures that all tasks will be guaranteed to be implemented sequentially.
Upvotes: 0
Reputation: 11280
If your intent is to use the CountDownLatch
to have the main()
method wait until all threads have executed, then you should move the latch.await()
outside the loop that submits the threads.
Also, you should not eat the InterruptedException
without setting the interrupted flag again. (see this article).
The correction would look like this :
for(int i=0;i<10;i++){
MyThread thread = new MyThread(i*10, ""+i,latch);
exec.execute(thread);
}
try {
latch.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
While this will certainly work, the Latch is suboptimal way to wait for the execution of a Runnable on another thread, when using an ExecutorService
. If you use submit()
rather than execute()
you can use the Future
returned by submit()
to wait for the completion of the submitted Runnable
by calling get()
on it.
Upvotes: 1
Reputation: 116888
So you are configuring a count down value of 10 new CountDownLatch(10)
but your code is only decrementing it once per thread. After you fork just 1 thread, you then wait for the latch but it is sitting at 9.
MyThread thread = new MyThread(i*10, ""+i,latch);
exec.execute(thread);
latch.await();
Not sure what you intended but maybe the latch.countDown();
should be inside the for loop in the thread?
for(int i=0;i<10;i++) {
...
// if you want the latch to count-down 10 times, it should be inside the loop
latch.countDown();
}
// it should not go here, outside the loop
If the goal is to wait for all of the jobs to finish, you can do that with the ExecutorService.awaitTermination(...)
method:
// submit jobs in loop
exec.shutdown();
exec.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
Also, you should not be extending Thread
in your MyThread
class. You should be implementing Runnable
. The only reason why your code works is that Thread
also implements Runnable
but MyThread
should not be a Thread
. The ExecutorService
takes a Runnable
or a Callable
, not a Thread
. It manages the threads for you internally to the service.
Upvotes: 3