0

If I define a class Team and implement two runnable interfaces inside that class, I do not get to a point in the program where the tasks by team1 and team2 ends. However if I implement the runnable directly in the class as in WorkerOne, I get to line where it prints tasks by WorkerOne ended. I do not understand why the task by team1 and team2 is never complete and the application is not stopping. I have included the code along with the console output below. I will appreciate any idea or thought. Thank you.

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

class WorkerOne implements Runnable {
    private CountDownLatch latch;

    public WorkerOne(CountDownLatch latch) {
        this.latch = latch;
    }

    @Override
    public void run() {
        System.out
                .println("[Tasks by WorkerOne : ]" + " :: " + "[" + Thread.currentThread().getName() + "]" + " START");
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        latch.countDown();
        System.out.println("[Tasks by WorkerOne : ]" + " :: " + "[" + Thread.currentThread().getName() + "]" + " END");

    }

}

class Team {
    private CountDownLatch latch;

    Runnable team1 = new Runnable() {
        public void run() {
            System.out.println("[Tasks by team1: ]" + " :: " + "[" + Thread.currentThread().getName() + "]" + "START");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            latch.countDown();
            System.out.println("[Tasks by team1 : ]" + " :: " + "[" + Thread.currentThread().getName() + "]" + " END");

        }
    };

    Runnable team2 = new Runnable() {
        public void run() {
            System.out.println("[Tasks by team2 : ]" + " :: " + "[" + Thread.currentThread().getName() + "]" + "START");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            latch.countDown();
            System.out.println("[Tasks by team2 : ]" + " :: " + "[" + Thread.currentThread().getName() + "]" + " END");

        }
    };
}

public class Demo {

    public static void main(String[] args) {
        CountDownLatch latch = new CountDownLatch(3);
        ExecutorService service = Executors.newFixedThreadPool(3);
        service.submit(new WorkerOne(latch));
        service.submit(new Team().team1);
        service.submit(new Team().team2);
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Tasks completed......");
    }
}

The console output is:

[Tasks by WorkerOne : ] :: [pool-1-thread-1] START
[Tasks by team1: ] :: [pool-1-thread-2]START
[Tasks by team2 : ] :: [pool-1-thread-3]START
[Tasks by WorkerOne : ] :: [pool-1-thread-1] END
Yogesh Ghimire
  • 432
  • 1
  • 8
  • 21

2 Answers2

0

The problem is because you do

    service.submit(new Team().team1);
    service.submit(new Team().team2);

The latch is a private member of Team, and you have created TWO instances of Team, each with its own latch.

I'm not sure why you're doing things this way, but I believe you want

    Team team = new Team();
    service.submit(team.team1);
    service.submit(team.team2);
Jim Garrison
  • 85,615
  • 20
  • 155
  • 190
0

The Team class' latch variable is never initialized. I suspect you intended, but forgot to, do this initialization, as you did in the WorkerOne class.

Executing the code as you posted it makes the Team runnables throw a NullPointerException when calling countDown() on the latch field. The main thread waits forever on its CountDownLatch as it will never be counted down to 0.

bowmore
  • 10,842
  • 1
  • 35
  • 43