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.