Java与Golang的WaitGroup等效

Golang has something called a WaitGroup which is sort of like in Java a CompletionService or a CountDownLatch or a Semaphore or some combination of the latter.

I'm not entirely sure how you would implement a WaitGroup in Java. I would imagine a custom CompletionService with some sort of Poison message would be the route to go (since queues can't say when they are done) but perhaps there is a better concurrent data structure/lock?

EDIT I posted a possible solution below using Semaphore that I think is more analogous than using thread.join.

After looking at the golang doc and confirming that Semaphore won't break with an enormous amount of permits I think a Semaphore set to Integer.MAX_VALUE is the closest to a golang WaitGroup.

The thread.join is probably more similar to how you would use WaitGroup with goroutines since it deals with the cleanup of the threads however an isolated WaitGroup just like a Semaphore is agnostic of what increments it.

CountdownLatch doesn't work because you need to know a priori how many threads you want to run and you cannot increment a CountdownLatch.

Assuming the semaphore is set to Integer.MAX_VALUE:

wg.Add(n) == semaphore.acquire(n)

wg.Done() == semaphore.release()

and in your thread where you want everything to stop:

wg.Wait() == semaphore.acquire(Integer.MAX_VALUE)

However I'm not sure all the semantics carryover so I'm not going to mark this correct for now.

public class WaitGroup {

    private int jobs = 0;

    public synchronized void add(int i) {
        jobs += i;
    }

    public synchronized void done() {
        if (--jobs == 0) {
            notifyAll();
        }
    }

    public synchronized void await() throws InterruptedException {
        while (jobs > 0) {
            wait();
        }
    }

}

WaitGroup has Add(delta) method that can be called after a WaitGroup has been created. CountDownLatch doesn't support this, number of tasks needs to be specified in advance. JDK7 Phaser can be used instead in this case:

phaser.register = wg.Add(1)
phaser.arrive = wg.Done
phaser.await = wg.Wait

No, there is no 'CountDownLatch' in Go.

sync.WaitGroup may have the 'wait task finish' feature, but this API's Add() doesn't happens-befor Done().