Lo normal es tener en algun sitio un contador, o un Vector, con los Threads que has lanzado. Y cuando un Thread acaba, notifica ese sitio para que reste uno o lo borrer del Vector. Cuando todos los Threads se han parado, el programa puede continuar.
Para parar el programa hasta entonces, notificarlo de que ha habido cambios en los Threads etc., pues lo que dijo HankmanC

.
Tambien puedes intentar usar el nuevo paquete java.util.concurrent donde hay clases como el ExecutorService que hacen cosas como las que pides.
http://www.deitel.com/articles/java_...ial_Part4.html
S!