Ao final do vídeo é explicado o recurso do join em Threads onde no exemplo citado a thread main vai aguardar a finalização da threadEnviaComando para continuar a sua execução. O que não ficou claro é o motivo de a threadRecebeResposta não continuar em execução após o término da threadEnviaComando, uma vez que a relação de join da execução é feita entre a thread main e threadEnviaComando
Segue a classe do Cliente.
package br.com.alura.cliente;
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Cliente {
public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException {
Socket s = new Socket("localhost", 12345);
System.out.println("Conexão estabelecida");
Thread threadEnviaComando = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("Pode enviar comandos");
PrintStream saida = new PrintStream(s.getOutputStream());
Scanner teclado = new Scanner(System.in);
while(teclado.hasNextLine()) {
String linha = teclado.nextLine();
if(linha.trim().isEmpty()) {
break;
}
saida.println(linha);
}
teclado.close();
saida.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
});
Thread threadRecebeResposta = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("Recebendo dados do servidor");
Scanner respostaServidor = new Scanner(s.getInputStream());
while (respostaServidor.hasNextLine()) {
String linha = respostaServidor.nextLine();
System.out.println(linha);
}
respostaServidor.close();
System.out.println("FIM Recebendo dados do servidor");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
});
threadEnviaComando.start();
threadRecebeResposta.start();
threadEnviaComando.join();
System.out.println("Fechando socket");
s.close();
System.out.println("Finalizando");
}
}