Este resumo do meu entendimento da comunicação entre threads no formato multi-thread Java discute principalmente a comunicação entre os threads em um código combinado com o texto. Portanto, extraí alguns códigos de exemplo no livro, e o conteúdo específico é o seguinte
① Sincronização
A sincronização mencionada aqui refere -se a vários threads usando a palavra -chave sincronizada para realizar a comunicação entre os threads.
Exemplo de referência:
public classe myObject {sincronizada public void methodA () {// Faça algo ....} Sincronizado public void methodB () {// Faça outra coisa}} classe pública threada estende thread {private myObject objeto; // omit o construtor @Override public void run () {super.run (); object.Methoda (); }} classe pública ThreadB estende Thread {Private MyObject Object; // omita o construtor @Override public void run () {super.run (); object.MethodB (); }} classe pública Run {public static void main (string [] args) {myObject Object = new MyObject (); // thread a e thread b segure o mesmo objeto: objeto threada a = new threada (objeto); Threadb B = new ThreadB (objeto); a.start (); b.start (); }}Como o thread a e o thread B seguram o objeto da mesma classe MyObject, embora esses dois threads precisem chamar diferentes métodos, eles são executados de maneira síncrona. Por exemplo, o encadeamento B precisa aguardar o thread a para executar o método MethodA () antes de executar o método MethodB (). Dessa forma, o thread A e o Thread B realizam a comunicação.
Este método é essencialmente a comunicação de "memória compartilhada". Vários encadeamentos precisam acessar a mesma variável compartilhada e quem obtém o bloqueio (obtém direitos de acesso), pode executá -la.
② Enquanto o método de pesquisa
O código é o seguinte:
importar java.util.arraylist; importar java.util.list; public class mylist {private list <strist> list = new ArrayList <string> (); public void add () {list.add ("elementos"); } public int size () {return list.size (); }} importar myList.mylist; public class Threada estende thread {lista mylist privada; public ThreadA (MyList List) {super (); this.list = list; } @Override public void run () {try {for (int i = 0; i <10; i ++) {list.add (); System.out.println ("adicionado" + (i + 1) + "elementos"); Thread.sleep (1000); }} catch (interruptEdException e) {e.printStackTrace (); }}} importar myList.mylist; public class ThreadB estende thread {Lista mylist privada; public ThreadB (MyList List) {super (); this.list = list; } @Override public void run () {try {while (true) {if (list.size () == 5) {System.out.println ("== 5, Thread B está pronto para sair"); lançar new interruptedException (); }}} catch (interruptEdException e) {e.printStackTrace (); }}} importar myList.mylist; importar extthread.threada; importar extthread.threadb; public class Test {public static void main (string [] args) {mylist service = new MyList (); Threada a = new threada (serviço); A.SetName ("A"); a.start (); Threadb B = new ThreadB (serviço); B.SetName ("B"); b.start (); }}Dessa forma, o encadeamento A altera constantemente as condições e ThreadB detecta constantemente se essa condição (list.size () == 5) é verdadeira através da instrução enquanto realiza a comunicação entre os threads. Mas esse método desperdiçará recursos da CPU. A razão pela qual desperdiça recursos é que, quando o agendador da JVM entrega à CPU para encadear B para execução, ela não faz nenhum trabalho "útil", mas está apenas testando se uma determinada condição é verdadeira. É semelhante à vida real, alguém continua analisando se o telefone está chegando na tela do seu telefone celular, em vez de: fazer outra coisa, quando um telefone está chegando, o toque o notificará que o telefone está chegando. Em relação ao impacto da pesquisa de threads, consulte: Quais são as consequências de um tópico executando um loop morto em java
③wait/notifique mecanismo
O código é o seguinte:
importar java.util.arraylist; importar java.util.list; public class mylist {private static list <string> list = new ArrayList <String> (); public static void add () {list.add ("anystring"); } public static int size () {return list.size (); }} classe pública threada estende o thread {bloqueio de objeto privado; public threada (bloqueio de objeto) {super (); this.lock = bloqueio; } @Override public void run () {try {synchronized (Lock) {if (myList.size ()! Lock.wait (); System.out.println ("Wait End" + System.currenttimemillis ()); }}} catch (interruptEdException e) {e.printStackTrace (); }}} classe pública ThreadB estende thread {private objeto bloqueado; public Threadb (bloqueio do objeto) {super (); this.lock = bloqueio; } @Override public void run () {try {Synchronized (Lock) {for (int i = 0; i <10; i ++) {myList.add (); if (myList.size () == 5) {Lock.Notify (); System.out.println ("notificado"); } System.out.println ("Adicionado" + (i + 1) + "elementos!"); Thread.sleep (1000); }}} catch (interruptEdException e) {e.printStackTrace (); }}} classe pública execute {public static void main (string [] args) {try {objeto bloqueio = new Object (); Threada a = new Threada (bloqueio); a.start (); Thread.sleep (50); Threadb B = novo ThreadB (Lock); b.start (); } catch (interruptedException e) {e.printStackTrace (); }}}O encadeamento A deve esperar que uma certa condição seja satisfeita antes de executar a operação. O thread B adiciona elementos à lista e altera o tamanho da lista.
Como A e B se comunicam? Em outras palavras, como o thread a sabe que a lista.size () já é 5?
Aqui usamos os métodos Wait () e notify () da classe de objeto.
Quando a condição não é atendida (list.size ()! = 5), encaixe as chamadas Wait () para abandonar a CPU e entra em um estado de bloqueio. --- Não pegue a CPU como ② enquanto pesquisas
Quando a condição é atendida, o Thread B chama notify () para notificar o encadeamento A. O chamado thread de notificação A é acordar o thread A e deixá-lo entrar em um estado executável.
Uma vantagem desse método é que a utilização da CPU aumentou.
Mas existem algumas desvantagens: por exemplo, o thread B é executado primeiro, adiciona 5 elementos ao mesmo tempo e chama notify () para enviar uma notificação e encadear um ainda executa; Quando o thread a executa e chama Wait (), ele nunca será despertado. Porque o Thread B já emitiu uma notificação e não emitirá nenhuma notificação no futuro. Isso mostra que a notificação é muito cedo e interromperá a lógica de execução do programa.
O exposto acima é tudo sobre este artigo, espero que seja útil para todos aprenderem a programação Java.