/ / Por que minha entrada está mostrando um thread em execução após outro, não ao mesmo tempo? - java, multithreading

Por que minha entrada está mostrando um thread executando após outro, não ao mesmo tempo? - java, multithreading

Eu pesquisei o conceito de um thread e vi que é para ter o código executado em dois processos ao mesmo tempo. Heres meu código embora

public class Connor extends Thread{

public void run() {
for(int i=0; i< 10; i ++){
System.out.println("Hello " + i);
}

public static void main(String[] args){
Connor runner1 = new Connor();
Connor runner2 = new Connor();
runner1.start();
runner2.start();
}
}

E minha saída http://imgur.com/yAZqgal

Parece que os dois tópicos começam emao mesmo tempo (processos separados, conforme indicado pelos dois 0s iniciais), mas um executa (1-9) e o outro executa (1-9). Eles também não devem entrelaçar (1,1,2,2, ...) porque os dois tópicos são impressos no console. Eu pesquisei e vi que start é o método certo para usar, pois diz à classe thread para executar o método run em outro thread? Alguém pode explicar por que estou recebendo essa saída?

Respostas:

5 para resposta № 1

Digamos que você tenha dez tarefas a fazer e que suairmã tem dez tarefas que ela precisa fazer, e você só tem um carro. Você traz o carro de volta após cada missão e troca de motorista? Claro que não. Isso seria absurdamente ineficiente. Cada thread basicamente precisa apenas do fluxo de saída. Portanto, seria absurdo intercalá-los com força.


3 para resposta № 2

Seu código parece bom. Eu acho que seus threads não são executados em paralelo apenas porque terminam rápido. Mude o limite do loop de 10 para 1000 e você verá o efeito.

O encadeamento inicial é relativamente pesadoOperação. Seu código inicia o primeiro thread e depois o segundo. O primeiro encadeamento iniciado uma vez termina antes que o segundo encadeamento tenha a chance de começar a executar sua lógica de negócios.


2 para resposta № 3

No caso do Multi-threading, não há garantiaaquele que thread é alocado por quanto tempo executar pelo processador e, nesse caso, o resultado é imprevisível e gerará uma saída diferente para cada execução.

Se você estiver procurando a saída desejada, precisará do bloco de sincronização. usando wait e notify você pode conseguir isso facilmente.

Veja abaixo a lição diretamente de Site oficial da Oracle:

Nota: wait E notify deve ser chamado dentro do synchronized bloquear e pode chamar o mesmo objeto no qual está sincronizado.

Código de amostra: (ler comentários embutidos)

public class Connor extends Thread {

private static Connor runner1 = new Connor();
private static Connor runner2 = new Connor();

public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Hello " + i);

// wake up another thread to come out from wait state
if (runner1 == this) {
// wake up runner2
synchronized (runner2) {
runner2.notify();
}
} else {
// wake up runner1
synchronized (runner1) {
runner1.notify();
}
}

synchronized (this) {
try {
// say current thread to wait until notify by another thread
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

public static void main(String[] args) {
runner1.start();
runner2.start();
}
}

saída:

Hello 0
Hello 0
Hello 1
Hello 1
Hello 2
Hello 2
Hello 3
Hello 3
Hello 4
Hello 4
Hello 5
Hello 5
Hello 6
Hello 6
Hello 7
Hello 7
Hello 8
Hello 8
Hello 9
Hello 9

0 para a resposta № 4

Por que minha entrada está mostrando um thread em execução após outro, não ao mesmo tempo?

A explicação geral é que o agendamento de threads é imprevisível. Intercalação pode acontecer ... ou não deve. Isso é fundamental para o encadeamento Java. (E, de fato, para segmentar na maioria dos outros idiomas.)

Se você precisar de execução de encadeamento para intercalar em umtotalmente previsível, você precisa implementar algum tipo de mecanismo de aperto de mão, em que um thread aguarda que outro faça alguma coisa e continue. Mas isso é complicado e geralmente anula o propósito de usar o encadeamento.

FWIW: A resposta do @Braj mostra como você pode implementar uma intercalação estrita. No entanto, observe que isso efetivamente significa que apenas um encadeamento será executado por vez. Além disso, a espera / notificação levará muito trabalho ao encadeamento agendador ... alguns dos quais o aplicativo será executado significativamente mais lento do que se você tivesse acabado de fazer o trabalho em um thread.


Neste exemplo em particular, há dois problemas que se combinam para tornar improvável qualquer intercalação de curto prazo:

  1. Criar um novo encadeamento nativo em Java érelativamente caro, porque normalmente envolve solicitar um bloco de memória do sistema operacional para abrigar a pilha de threads. Isso, por sua vez, implica no sistema operacional "mexendo" com as tabelas de páginas, zerando um bloco de memória e assim por diante.

  2. O planejamento de encadeamento nativo é implementado pelosistema operacional e opera em um nível de granulação bastante grossa ... porque essa é a maneira mais eficiente de operar da perspectiva de um aplicativo típico. (A alternância de "contextos" de encadeamento em uma máquina da classe PC é uma operação relativamente cara, e o próprio planejador de encadeamentos tem trabalho a fazer.

No seu exemplo, as chances são de que o primeiro segmento possa dizer "olá" dez vezes antes de o segundo segmento estar pronto para ser agendado.