Abhishek Choudhary
Abhishek Choudhary

Reputation: 8395

Not getting expected output while using Countdownlatch and Executor in java

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

Answers (3)

Abhishek Choudhary
Abhishek Choudhary

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

bowmore
bowmore

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

Gray
Gray

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

Related Questions