gstackoverflow
gstackoverflow

Reputation: 36984

Application hangs when I invoke join inside CyclicBarrier callback

I have the following method test where I start threads:

public static void main(String[] args) throws InterruptedException {
        List<Thread> threads = new ArrayList<>();
        final CyclicBarrier cyclicBarrier = new CyclicBarrier(1);
        Thread thread = new Thread(new CallbackThread(cyclicBarrier, threads));
        threads.add(thread);
        thread.start();          
    }

CallBack thread looks like this:

class CallbackThread implements Runnable {
    CyclicBarrier cyclicBarrier;
    List<Thread> threads;

    CallbackThread(CyclicBarrier cyclicBarrier, List<Thread> threads) {
        this.cyclicBarrier = cyclicBarrier;
        this.threads = threads;
    }

    @Override
    public void run() {
        try {
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (BrokenBarrierException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        System.out.println("Threads started");
        for (Thread thread1 : threads) {
            try {
                thread1.join();
            } catch (InterruptedException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
        }
        System.out.println("Threads finished");

    }
}

When I run application I see following output:

Threads started

and application hangs.

I don understand why.

If to replace join logic to main method - all goods well.

public static void main(String[] args) throws InterruptedException {
        List<Thread> threads = new ArrayList<>();
        final CyclicBarrier cyclicBarrier = new CyclicBarrier(1);
        Thread thread = new Thread(new CallbackThread(cyclicBarrier, threads));
        threads.add(thread);
        thread.start();
        for (Thread thread1 : threads) {
            try {
                thread1.join();
            } catch (InterruptedException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
        }
        System.out.println("Threads finished");

    }

Can you explain this difference.
IMHO it should work same.

Upvotes: 0

Views: 154

Answers (2)

Narendra Pathai
Narendra Pathai

Reputation: 41945

You are joining on self. That's why the program never ends.

When you call the join() from Main thread, then main thread is trying to join the thread it created which is CallableThread. So it is proper.

But when you join in CallableThread, then you are passing threads[] which contains the reference to itself. So it is joining itself, which will not end.

Upvotes: 1

morpheus05
morpheus05

Reputation: 4872

The code from your first example calls join on its own thread. You add it to the list and the thread iterates over the list and joins every thread inside the list.

Upvotes: 2

Related Questions