Este artigo estuda principalmente exemplos de código relacionados da tecnologia tradicional de comunicação de sincronização de threads da simultaneidade de Java, como segue.
Vejamos uma pergunta primeiro:
Existem dois tópicos. O encadeamento infantil é executado 10 vezes primeiro, depois o encadeamento principal é executado 5 vezes e depois muda para o encadeamento filho executa 10 e, em seguida, o encadeamento principal é executado 5 vezes ... Esta viagem de ida e volta é 50 vezes.
Depois de ler esta pergunta, é óbvio que a comunicação entre threads é usada. Deixe-me analisar a idéia primeiro: primeiro deve haver dois threads e, em seguida, deve haver 50 loops em cada thread, porque cada thread precisa executar tarefas 50 vezes a viagem de ida e volta, a tarefa do thread principal é executar 5 vezes e a tarefa do thread infantil é executar 10 vezes. A tecnologia de comunicação entre thread usa principalmente wait() e notify() . O método Wait () faz com que o fio atual espere e solte a trava mantida. notify() indica que um único thread aguardando esse monitor de objeto é despertado. Vamos concluir esse problema de comunicação entre thread passo a passo.
Primeiro, independentemente da comunicação entre o tópico principal e o thread infantil, escreva as tarefas a serem executadas por cada thread:
public class tradicionalthreadCommunication {public static void main (string [] args) {// Abra um thread filho novo thread (new runnable () {@Override public void run () {for (int i = 1; i <= 50; i ++) {synchronized (tradicional) {System.out.println ("Sub Thread Sequence de" +j +", loop de" +i);}}}}}}). Start (); // método principal é o encadeamento principal para (int i = 1; i <= 50; i ++) {synchronized (tradicional) {System.out.println ("Sequência de threads principal de" + j + ", loop de" + i);}}}}}}}}}}}}}}}}}}}}}Como mencionado acima, os dois threads têm 50 loops grandes e executam 50 tarefas, a tarefa do encadeamento da criança é executada 10 vezes e a tarefa do thread principal é executada 5 vezes. Para garantir a sincronização entre dois threads, são usados blocos de código de sincronização sincronizados e o mesmo bloqueio é usado: objeto bytecode da classe. Isso garante a segurança do thread. Mas esse design não é muito bom. Assim como eu escrevi no impasse na seção anterior, podemos colocar tarefas de threads em uma aula. O padrão desse design é mais estruturado, e colocar diferentes tarefas de encadeamento na mesma classe resolverá facilmente o problema de sincronização, pois é fácil usar o mesmo bloqueio em uma classe. Portanto, modifique o programa acima:
public class tradicionalthreadCommunication {public static void main (string [] args) {negócios negócios = new Business (); // novo A thread Task Processing Class // Abra um thread Child Thread (new Runnable () {@Override Void run () {para (int i = 1; i <= 50; i ++) {Business.S.s.s.s {para (int i = 1; i <= 50; i ++) {Business.s.s.s.s.sub (Int I = 1; i <= 50; i ++) {Business.s.s.s.su (para (int i); Tópico principal para (int i = 1; i <= 50; i ++) {bussiness.main (i);}}} // Os dados comuns (incluindo bloqueios de sincronização) ou vários métodos comuns a serem usados devem ser classificados na mesma classe. Esse design reflete apenas a robustez do programa de cluster de alta classe. classe Business {public sincronizado void sub (int i) {for (int j = 1; j <= 10; j ++) {System.out.println ("Sub Thread Sequence de" +j +", loop de" +i);}} syncronized public void main (int i) {para (int j = 1; j < j + ", loop de" + i);}} Após essa modificação, a estrutura do programa se torna mais clara e mais robusta. Basta adicionar a palavra -chave sincronizada aos dois métodos de tarefa de thread e usar esse bloqueio. Mas ainda não há comunicação entre os dois tópicos. O resultado da execução é que o thread principal aparece na tarefa 50 vezes e o encadeamento infantil aparece na tarefa 50 vezes. O motivo é muito simples, porque há sincronização sincronizada.
A seguir, continua a melhorar o programa para permitir a comunicação entre os dois threads, conforme descrito na pergunta:
public class tradicionalthreadCommunication {public static void main (string [] args) {negócios negócios = new Business (); // novo A thread Task Processing Class // Abra um thread Child Thread (new Runnable () {@Override Void run () {para (int i = 1; i <= 50; i ++) {Business.S.s.s.s {para (int i = 1; i <= 50; i ++) {Business.s.s.s.s.sub (Int I = 1; i <= 50; i ++) {Business.s.s.s.su (para (int i); Tópico principal para (int i = 1; i <= 50; i ++) {bussiness.main (i);}}} // para usar dados comuns (incluindo bloqueios de sincronização) ou vários métodos comuns devem ser classificados na mesma classe. Esse design apenas reflete a robustez do drama de Gao Lei e o programa. classe Business {Private boolean bshouldSub = true; public sincronizado void sub (int i) {while (! bShouldSub) {// Se não for a sua vez de executar, tente {this.wait (); // o objeto que chama o método Wait () deve ser o mesmo que o objeto sinCronizado. Aqui o sincronizado está no método; portanto, use este} catch (interruptEdException e) {// TODO GATO GENERADO AUTOMAGEM BLOCKE.printStackTrace ();}} para (int j = 1; j <= 10; j ++) {System.out.println ("Sub sequência de" + j + ", loop de" LOOP de ") {System.out.println (" Sub; this.notify (); // acorde o fio principal aguardando} public sincronizado void main (int i) {while (bshouldSub) {// se não for a sua vez para executar, tente {this.wait ();); ++) {System.out.println ("Sequência de threads principal de" + j + ", loop de" + i);} bshouldsub = true; // altere a tag this.notify (); // acorde o encadeamento infantil em espera}}}Primeiro de tudo, não vamos falar sobre a implementação específica do programa, de uma perspectiva estrutural, já percebemos os benefícios desse design: não há necessidade de modificar nada na função principal e a lógica sobre a sincronização entre tipos e a comunicação entre thread está na classe executiva. Diferentes encadeamentos na função principal precisam chamar as tarefas correspondentes colocadas na classe. Reflete os benefícios do alto relevo.
Vejamos o código específico novamente. Primeiro, defina uma variável booleana para identificar qual encadeamento deve ser executado. Quando não é o fio infantil, ele dormirá. Em seguida, ele executará naturalmente o thread principal. Após a execução, ele modificará o BSHOULDSUB e acordará o tópico infantil. Neste momento, o tópico infantil julgará que, embora não esteja satisfeito e não dormirá. Ele executará a tarefa do tópico infantil. Da mesma forma, depois que o thread principal apenas modificou o BSHOULDSUB, quando o segundo loop é usado para executar a tarefa principal do encadeamento, ele dormirá e aguarda o tópico infantil acordar. Isso deixa a lógica muito clara. O fio principal e o fio infantil se revezam para executar suas respectivas tarefas, e esse ritmo é 50 vezes no total.
Há outra pequena explicação: é realmente possível usar se para julgar, mas por que usar enquanto? Porque às vezes os threads acordam Fakely (é como um sono, que obviamente está dormindo, mas se levanta). Se ele usar se, depois de Fakely acordar, ele não voltará a julgar se e, naturalmente, ele executará a tarefa. Ok, outro thread está executando e afetará outro thread em um flash. Mas se for um tempo, será diferente. Mesmo que o tópico esteja falsamente acordado, ele ainda julgará enquanto. No entanto, o outro thread está executando neste momento. O BSHOULDSUB não foi modificado, por isso ainda entra enquanto está dormindo novamente ~, por isso é muito seguro e não afetará o outro tópico! Isso também é feito no documento JDK oficial.
Vamos resumir a comunicação entre threads.
O exposto acima é toda a explicação detalhada do código de tecnologia de comunicação de sincronização de threads tradicional de simultaneidade de Java, e espero que seja útil para todos. Amigos interessados podem continuar se referindo a outros tópicos relacionados neste site. Se houver alguma falha, deixe uma mensagem para apontá -la. Obrigado amigos pelo seu apoio para este site!