Várias maneiras de implementar o modelo de produtor e consumidor
Veja o exemplo em nossas vidas como exemplo. Os produtos produzidos pelas fábricas são sempre exportados para usar fora. Este é o conceito de produção e consumo.
Em nosso processo real de desenvolvimento de software, geralmente encontramos os seguintes cenários: um módulo é responsável pela geração de dados e esses dados são processados por outro módulo (o módulo aqui é generalizado, que pode ser classes, funções, threads, processos etc.).
O módulo que gera dados é vividamente chamado de produtor; enquanto o módulo que processa dados é chamado de consumidor.
O primeiro tipo: Use Wait-Notify para implementar o produtor e o modelo de consumidor
1. Um produtor e um consumidor:
2. Um produtor e vários consumidores:
O segundo tipo: usando filas de bloqueio para implementar o produtor e o modelo de consumidor
3. Use filas de bloqueio para implementar o padrão do consumidor do produtor
Eu acredito que todo mundo foi para a culinária japonesa. Há uma refeição muito atraente que é churrasco. O mestre do churrasco ficará do lado e continuará churrasco e depois colocará a carne assada em um prato; E nós, comensais que estão babando, ficaremos de lado, e continuaremos comendo enquanto houver carne no prato.
Neste caso de vida, o mestre de churrasco é o produtor e ele é responsável pelo churrasco. Após a torrefação, ele coloca a carne no prato em vez de entregá -la diretamente ao restaurante (ou seja, não há necessidade de notificar o restaurante para comer carne). Se a carne no prato estiver cheia, o mestre parará por um tempo até que alguém come o churrasco antes de produzir a carne; E os clientes estão apenas olhando para o prato e, uma vez que há carne no prato, somos responsáveis por comê -lo;
Durante todo o processo, os clientes e o mestre de churrasco não lidaram diretamente entre si, mas interagiram com o prato.
A placa atua como um conceito de buffer. Se algo for produzido, coloque -o. A placa também possui um limite de tamanho. Se exceder o tamanho da placa, bloqueará a produção do produtor e aguardará o consumidor; Quando a placa estiver vazia, bloqueia o consumo do consumidor e aguarda o produtor produzir.
Bloquear a fila durante a programação pode cumprir a função do disco.
Características de bloquear filas:
Quando o elemento da fila estiver cheio, bloqueie a operação de inserção;
Quando o elemento da fila está vazio, a operação de aquisição é bloqueada.
Tanto o ArrayBlockockQueue quanto o LinkedBlockingQueue suportam FIFO (primeiro a entrar), mas o LinkedBlockingQuee é ilimitado, enquanto o ArrayBlockingQueue é delimitado.
O seguinte usa filas de bloqueio para implementar produtores e consumidores:
Produtor:
importar java.util.concurrent.blockingQueue; o produtor de classe pública implementa Runnable {private final BlockingQueue BlockingQueue; // Defina o tamanho do cache da fila. A produção será interrompida temporariamente após exceder esse tamanho durante o processo de produção. Final privado Int Queue_size = 10; Produtor público (BlockingQueue BlockingQueue) {this.blockingQueue = BlockingQueue;} int Task = 1; @Override public void Run () {while (True) {Trys {System.out.Println (Produção: "+Task); // PuttUt O Product para {System.Ot.PriTln (Production:"+Task); um tempo para facilitar a visualização do encadeamento do efeito.consumidor:
importar java.util.concurrent.blockingQueue; // Classe pública de consumo A classe consumidor implementa o Runnable {private final BlockingQueue BlockingQueue; consumidor público (BlockingQueue BlockingQueue) {thelbockquee = Blockeue;}@substitua public void () {// To Lei, como se houve uma tarefa, a tarefa é uma tarefa, que é a TOTETETETETETETESTETETE; {System.out.println ("Consumindo:" + BlockingQueue.take ()); // Deixe que ele pare por um tempo para facilitar a visualização do efeito Thread.sleep (2000);} catch (interruptedException e) {e.printstacktrace ();}}}}}}}}}}}teste:
importar java.util.concurrent.blockockQueue; importar java.util.Concurrent.LinkedBlockingQueue;/** * Modo do consumidor do produtor * Use bloqueio da fila BlockingQueue * @author WangGenshen * */public classCoPro {public static void Main (string [] p = novo produtor (BlockingQueue); consumidor c = novo consumidor (blockingqueue); thread tp = novo thread (p); thread tc = novo thread (c); tp.start (); tc.start ();}}Como o LinkedBlockingQueue é uma fila ilimitada, os produtores continuarão a produzir, colocar as tarefas produzidas na fila e os consumidores consumirão na fila:
Se você usar a fila de bloqueio limitada, em vez disso, poderá inicializar o tamanho da fila. Então, quando os elementos da fila excederem o tamanho da fila, o produtor aguardará o consumidor para consumir um e depois produzir o outro:
Código de teste:
Inicialize um ArrayBlockingQueue do tamanho 10:
public static void main (string [] args) {BlockingQueue BlockingQueue = novo ArrayBlockingQueue (10); Produtor P = novo produtor (BlockingQueue); consumidor C = novo consumidor (BlockingQueue); Thread TP = novo Thread (P); Thread = New Thread (C); tp.start ();Durante o teste, os produtores foram autorizados a produzir um pouco mais rápido, enquanto os consumidores eram mais lentos. Você pode ver que a diferença entre o número de série do produto produzido e o número de série do produto consumido é sempre 10 (o tamanho da fila):
Resumir
O exposto acima está o conteúdo inteiro deste artigo sobre o método de implementação do modelo de consumidor de produção e os exemplos de código de problemas de segurança de threads. 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!