A comunicação de threads é usada para garantir a operação coordenada dos threads. Geralmente, a comunicação de threads precisa ser considerada ao fazer sincronização de threads.
1. Comunicação tradicional de threads
Geralmente, são usados três métodos fornecidos pela classe Objectlt:
Esses três métodos devem ser chamados pelo objeto Monitor de Sincronização e são divididos em duas situações:
Ao sincronizar métodos, como o monitor de sincronização é esse objeto, esses três métodos podem ser chamados diretamente.
Exemplos são os seguintes:
classe pública syncmethodThreadCommunication {classe estática datawrap {int data = 0; bandeira booleana = false; public sincronizado void addThreadA () {if (flag) {try {wait (); } catch (interruptedException e) {e.printStackTrace (); }} dados ++; System.out.println (thread.currentThread (). GetName () + "" + dados); bandeira = true; notificar (); } public sincronizado void addThreadB () {if (! flag) {try {wait (); } catch (interruptedException e) {e.printStackTrace (); }} dados ++; System.out.println (thread.currentThread (). GetName () + "" + dados); bandeira = false; notificar (); }} classe estática threada estende o thread {privado datawrap data; public threada (datawrap datawrap) {this.data = datawrap; } @Override public void run () {for (int i = 0; i <10; i ++) {data.addthreadA (); }}} classe estática ThreadB estende thread {Datawrap privado; public threadb (datawrap datawrap) {this.data = datawrap; } @Override public void run () {for (int i = 0; i <10; i ++) {data.addthreadb (); }}} public static void main (string [] args) {// implemente dois threads para adicionar dados por sua vez datawrap datawrap = new datawrap (); new ThreadA (DataWrap) .Start (); novo threadb (datawrap) .start (); }}Ao sincronizar os blocos de código, você precisa usar o objeto Monitor para chamar esses três métodos.
Exemplos são os seguintes:
classe pública syncblockthreadComminication {classe estática datawrap {sinalizador boolean; int dados; } classe estática threada estende thread {datawrap datawrap; public threada (datawrap datawrap) {this.datawrap = datawrap; } @Override public void run () {for (int i = 0; i <10; i ++) {synchronized (datawrap) {if (datawrap.flag) {try {datawrap.wait (); } catch (interruptedException e) {e.printStackTrace (); }} datawrap.data ++; System.out.println (getName () + "" + datawrap.data); datawrap.flag = true; datawrap.Notify (); }}}}} classe estática threadb estende thread {datawrap datawrap; public threadb (datawrap datawrap) {this.datawrap = datawrap; } @Override public void run () {for (int i = 0; i <10; i ++) {synchronized (datawrap) {if (! Datawrap.flag) {try {datawrap.wait (); } catch (interruptedException e) {e.printStackTrace (); }} datawrap.data ++; System.out.println (getName () + "" + datawrap.data); datawrap.flag = false; datawrap.Notify (); }}}} public static void main (string [] args) {// implemente dois threads para adicionar dados por sua vez datawrap datawrap = new datawrap (); new ThreadA (DataWrap) .Start (); novo threadb (datawrap) .start (); }}2. Use a condição para controlar a comunicação de threads
Ao usar um objeto de bloqueio para garantir a sincronização, um objeto de condição é usado para garantir a coordenação.
Exemplos são os seguintes:
import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;import com.sun.media.sound.RIFFInvalidDataException;import javafx.scene.chart.PieChart.Data;public class SyncLockThreadCommunication { classe estática datawrap {int data; bandeira booleana; bloqueio final privado de bloqueio = new reentrantlock (); condição final privada condição = bloqueio.newcondition (); public void addThreadA () {Lock.lock (); tente {if (flag) {try {condition.await (); } catch (interruptedException e) {e.printStackTrace (); }} dados ++; System.out.println (thread.currentThread (). GetName () + "" + dados); bandeira = true; condicional.Signal (); } finalmente {Lock.unlock (); }} public void addThreadB () {Lock.lock (); tente {if (! flag) {tente {condition.await (); } catch (interruptedException e) {e.printStackTrace (); }} dados ++; System.out.println (thread.currentThread (). GetName () + "" + dados); bandeira = false; condicional.Signal (); } finalmente {Lock.unlock (); }}} classe estática threada estende Thread {datawrap datawrap; public threada (datawrap datawrap) {this.datawrap = datawrap; } @Override public void run () {for (int i = 0; i <10; i ++) {datawrap.addthreada (); }}} classe estática threadb estende thread {datawrap datawrap; public threadb (datawrap datawrap) {this.datawrap = datawrap; } @Override public void run () {for (int i = 0; i <10; i ++) {datawrap.addthreadb (); }}} public static void main (string [] args) {// implemente dois threads para adicionar dados por sua vez datawrap datawrap = new datawrap (); new ThreadA (DataWrap) .Start (); novo threadb (datawrap) .start (); }}Os métodos Await (), Singal () e Singalall () do objeto de condição correspondem aos métodos Wait (), Notify () e NotifyAll (), respectivamente.
3. Use bloqueio de bloqueio de bloqueio para controlar a comunicação de threads
O BlockingQueue é uma sub-interface da interface da fila, que é usada principalmente para comunicação de threads. Ele tem um recurso: quando o thread do produtor tenta colocar um elemento no BlockingQueue, se a fila estiver cheia, o thread será bloqueado; Quando o thread do consumidor tenta retirar o elemento do BlockingQueue, se a fila estiver vazia, a rosca será bloqueada. Esses dois recursos correspondem a dois métodos que suportam o bloqueio, put (e e) e tire ()
Exemplos são os seguintes:
importar java.util.concurrent.arrayblockQueue; importar java.util.concurrent.blockingQueue; classe pública BlockingQueuethReadComminication {classe estática datawrap {int data; } classe estática threada estende o thread {private BlockingQueue <dawrap> BlockingQueue; public Threada (BlockingQueue <dawrap> BlockingQueue, nome da string) {super (nome); this.blockingQueue = BlockingQueue; } @Override public void run () {for (int i = 0; i <100; i ++) {try {datawrap datawrap = blockingQueue.take (); datawrap.data ++; System.out.println (getName () + "" + datawrap.data); sono (1000); } catch (interruptedException e) {e.printStackTrace (); }}}}} classe estática threadb estende o thread {private BlockingQueue <datawrap> bockingQueue; DataWrap DatapAp privado; public ThreadB (BlockingQueue <dawrap> BlockingQueue, DataWrap DataWrap, Nome da String) {Super (Nome); this.blockingQueue = BlockingQueue; this.datawrap = datawrap; } @Override public void run () {for (int i = 0; i <100; i ++) {try {datawrap.data ++; System.out.println (getName () + "" + datawrap.data); blockingqueue.put (datawrap); sono (1000); } catch (interruptedException e) {e.printStackTrace (); }}}} public static void main (string [] args) {/// implementa dois threads para adicionar dados por sua vez datawrap datawrap = new Datawrap (); BlockingQueue <dawrap> BlockingQueue = novo ArrayBlockingQueue <> (1); novo Threada (BlockingQueue, "Consumidor"). Start (); novo ThreadB (BlockingQueue, DataWrap, "Produtor"). Start (); }}BlockingQueue tem cinco classes de implementação:
ArrayblockockQueue BlockingQuee Fileue com base na implementação da matriz
LinkedBlockockQueue BlockingQueue
Os elementos no PriorityBlockingQueue precisam implementar a interface comparável e a ordem dos elementos é personalizada classificada pelo comparador.
O síncrono sincroniza a fila, exigindo que as operações de acesso na fila sejam executadas alternadamente.
Os elementos de coleta de atraso devem implementar a interface de atraso, e os elementos na fila são classificados de acordo com o valor de retorno do método da interface de atraso getDelay ().
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.