1. Conceito
O problema de produtores e consumidores é um problema de colaboração multithread em jindian. Os produtores são responsáveis por produzir produtos e armazená -los no armazém; Os consumidores obtêm produtos do armazém e os consumem. Quando o armazém está cheio, o produtor deve interromper a produção até que haja um local para o produto ser armazenado; Quando o armazém está vazio, o consumidor deve interromper o consumo até que haja um produto no armazém.
As seguintes técnicas são usadas principalmente para resolver problemas de produtor/consumidor: 1. Use threads para simular produtores e armazenar continuamente produtos no armazém no método de execução. 2. Use threads para simular os consumidores e obter continuamente produtos do armazém no método de execução. 3
O . A classe do armazém salva o produto. Quando o número de produtos é 0, o método de espera é chamado, fazendo com que o thread atual do consumidor insira um estado de espera. Quando um novo produto é armazenado, o método Notify é chamado para acordar o tópico do consumidor em espera. Quando o armazém está cheio, o método de espera é chamado, fazendo com que o atual thread do produtor insira um estado de espera. Quando um consumidor obtém o produto, o método Notify é chamado para acordar o tópico do produtor em espera.
2. Exemplos
Pacote Book.Thread.Product; Public Class Consumer estende thread {Private Warehouse Warehouse; // O armazém em que o consumidor obtém o produto Boolean Private Boolean Running = false; // é o bit de sinalizador do thread de thread de thread exigido (Warehouse Warehouse, Nome String) {super (nome); this.warehouse = armazém; } public void start () {this.running = true; super.start (); } public void run () {Product Product; tente {while (em execução) {// obtenha o produto do armazém = warehouse.getproduct (); sono (500); }} catch (interruptEdException e) {e.printStackTrace (); }} // pare o thread do consumidor public void stopconsumer () {sincronizado (warehouse) {this.running = false; warehouse.NotifyAll (); // Notifique o thread aguardando o armazém}} // se o thread do consumidor está executando public boolean iSrunning () {retorna em execução; }} pacote book.thread.product; o produtor de classe pública estende thread {armazém de armazém privado; // O fabricante armazena o armazém do produto privado estático int producename = 0; // o nome do produto Private Boolean Running = False; // O bit de sinalizador do thread final é necessário produtor público (nome de warehouse); this.warehouse = armazém; } public void start () {this.running = true; super.start (); } public void run () {Product Product; // Produza e armazenar o produto, tente {while (em execução) {Product = new Product ((++ ProductName)+""); this.warehouse.StorageProduct (Product); sono (300); }} catch (interruptEdException e) {e.printStackTrace (); }} // pare o thread do produtor public void stopProdUcer () {sincronizado (warehouse) {this.running = false; // notifique o tópico que aguarda o armazém armazém warehouse.NotifyAll (); }} // se o thread do produtor está executando public boolean isrunning () {return Running; }} pacote book.thread.product; public class Product {private string name; // Nome do produto Public Product (nome da string) {this.name = name; } public string tostring () {return "Product-"+nome; }} Package Book.Thread.Product; // A classe de armazém do produto usa uma matriz para representar uma fila circular para armazenar o produto Public Class Warehouse {private static int capacidade = 11; // a capacidade do warehouse Private Product [] Produtos particulares; // Produtos de Warehouse // Nas do 1º de Substeto, traseiro] Não é um dos produtos privados; private int traseiro = 0; // Subscrito do último produto não consumido no armazém mais 1 Public Warehouse () {this.Products = New Product [Capacidade]; } Public Warehouse (int capacidade) {this (); if (capacidade> 0) {capacidade = capacidade +1; this.products = novo produto [capacidade]; }} // Obtenha um produto do armazém public Product getProduct () lança interruptedException {Synchronized (this) {boolean ConsumerRunning = true; // tag Se o thread de consumo ainda está executando o ThreadThread = Thread.CurrentThread (); // obtenha o current If (CurrentThread de consumer) {threads). } else {return null; // não consumidor pode obter o produto} // Se o thread do consumidor estiver em execução, mas não há produto no armazém, o thread do consumidor continua esperando enquanto ((front == traseiro) && consumerrunning) {wait (); consumerrunning = ((consumidor) CurrentThread) .IsRunning (); } // Se o thread do consumidor parou de funcionar, saia do método e cancele o produto se (! Consumerrunning) {return null; } // Obtenha o primeiro produto que não foi consumido atualmente Produto Produto = Produtos [Frente]; System.out.println ("Consumer ["+currentThread.getName ()+"] getProduct:"+Product); // mova o subscrito do produto atualmente não consumido, um por um, se atingir o final da matriz, mova para o cabeçalho frontal = (front+1+capacidade)%capacidade; System.out.println ("A quantidade de produtos ainda não consumidos no armazém:"+(traseira+capacidade de capacidade)%capacidade); // notificar outros threads em espera notificar (); produto de retorno; }} // Armazene um produto no armazenamento público do armazenamento público de armazenamento (produto) lança interruptEdException {Synchronized (this) {boolean Prodernning = true; // Assine se o thread do produtor está executando o Thread CurrentThread = Thread.CurrentThread (); if (CurrentThread instância do produtor) {ProductErNning = ((Produtor) CurrentThread) .isrunning (); } else {return; } // Se o último produto não consumido estiver próximo ao subscrito do primeiro produto não consumido, significa que não há espaço de armazenamento. // Se não houver espaço de armazenamento e o thread do produtor ainda estiver em execução, o thread do produtor aguarda o armazém liberar o produto enquanto (((traseiro+1)%de capacidade == FRONT) && ProduDERRunning) {wait (); ProductErNning = ((Produtor) CurrentThread) .IsRunning (); } // Se o encadeamento de produção parou de funcionar, o armazenamento do produto será interrompido se (! ProductErunning) {return; } // salve o produto nos produtos do armazém [traseiro] = produto; System.out.println ("Produtor [" + Thread.currentThread (). GetName () + "] StorageProduct:" + Product); // Altere o subscrito traseiro um após o outro. Traseira = (traseira + 1)%de capacidade; System.out.println ("A quantidade de produtos não consumidos no armazém:" + (Capacidade traseira + capacidade -frente)); notificar (); }}} Package Book.thread.Product; public class TestProduct {public static void main (string [] args) {warehouse warehouse = new warehouse (10); // Crie um armazém com uma capacidade de 10 // criar threads e produtores de consumidores1 = produtores de novos produtores (Warehouse "; Produtores Produtores2 = Novo Produtor (Warehouse, "Produtor-2"); Produtores Produtores3 = Novo Produtor (Warehouse, "Produtor-3"); Consumidor consumidor1 = novo consumidor (armazém, "consumer-1"); Consumidor consumidor2 = novo consumidor (armazém, "consumer-2"); Consumidor consumidor3 = novo consumidor (armazém, "consumidor-3"); Consumidor consumidor4 = novo consumidor (armazém, "consumidor-4"); // Inicie o thread do produtor e o thread do consumidor produz1.start (); produtores2.start (); consumer1.start (); produtores3.start (); consumer2.start (); consumer3.start (); consumer4.start (); // Deixe o Programa Produtor/Consumidor executar 1600ms Try {Thread.sleep (1600); } catch (interruptedException e) {e.printStackTrace (); } // Stop the Consumer Thread Produces1.StopProdUcer (); consumer1.stopConsumer (); produtores2.StopProducer (); consumer2.stopConsumer (); produtores3.StopProducer (); consumer3.stopConsumer (); consumer4.stopConsumer (); }}Resultado da saída:
Produtor [Produtter-1] StorageProduct: O número de produtos que não foram consumidos no armazém do produto-1: 1consumer [Consumer-2] getProduct: o número de produtos que não foram consumidos no armazenamento de produtos: o número de produtos: o número de produtos: o número de produtos: o número de produtos: o número de produtos: o número de produtos: o número de produtos: o número de produtos: o número de produtos: o número de produtos: o número de produtos: o número de produtos: o número de produtos: o número de produtos: o número de produtos: o número de produtos: o número de produtos: o número de storage-3: o número de storage: o número de produtos que não foram consumidos e o que não foi consumido. não foram consumidos no armazém do Produto-2: 2Consumer [Consumer-3] GetProduct: o número de produtos que não foram consumidos no armazém do produto-3: 1consumer [Consumer-1] getProduct: o número de produtos que não foram consumidos no produto: o número de produtos do produto: o número de produtos do produto: o número de produtos do produto: o número de produtos do produto: o número de produtos do produto: o número de produtos do produto: o número de produtos do produto: o número de produtos do produto: o número de produtos do produto: o número de produtos do produto: o número de produtos do produto: o número de produtos do produto: o número de produtos de uso do produto: o número de produtos do produto: o número de produtos do produto: o número de produtos do produto. 1CONSUMER [consumidor-4] getProduct: o número de produtos que não foram consumidos no armazenamento do produto-4: 0Produced [Produtter-3] StorageProduct: o número de produtos que não foram consumidos no armazenamento: o número de resumos: o número de resumos: o número de resumos: o número de resumos: o número de summas. getProduct: o número de produtos que não foram consumidos no armazém do produto-6: 1consumer [consumidor-2] getProduct: o número de produtos que não foram consumidos no armazém do produto 5: o número de produtos que não foram consumidos no produto: o número de consumidores: o número de produtos que não foram consumidos no produto-7) [product-1]. No armazém do Produto-7: 0PRODUCER [Product-3] StorageProduct: o número de produtos que não foram consumidos no armazenamento do Produto-8: 1Produtor [Produtor-2] StorageProduct: Product 9 Número de produtos que não foram consumidos no número de produtos do Warehouse: 2 anos e consumidores do consumidor-9 são consumidos pelo número de produtos mais consumidos: o número de resumores mais consumidores [consumidor-4]. 1Producer [produttr-1] StorageProduct: Product-10 Número de produtos que não foram consumidos no armazém: 2Producer [Product-3] StorageProduct: Product-11 de produtos que não foram consumidos no armazém: 3Producer [produtr-2] StorageProduct: Product-12 de produtos que não foram considerados Número de produtos que não foram consumidos no armazém: 3consumer [Consumer-2] GetProduct: Product-10 Número de produtos que não foram consumidos no armazém: 2Consumer [Consumer-3] getProduct: Product-11 Número de produtos que não foram consumidos no wearehouse: 1 do 1producedor [ProductTr-3] 2PRODUCER [Produtr-1] StorageProduct: Produto-14 Número de produtos que não foram consumidos no armazém: 3Producer [Produtor-2] StorageProduct: Product-15 Número de produtos que não foram consumidos no armazém: 4Consumer [Consumer-4] GetProduct: Product-12 de produtos que não foram Número de produtos que não foram consumidos no armazém: 2COnsumer [Consumer-2] GetProduct: Produto-14 Número de produtos que não foram consumidos no armazém: 1producedor [produttr-1] StorageProduct: produtor-16 Número de produtos que não foram consumidos no warehouse: 2producer [produtor-3] armazenamento de armazenamento 3PRODUCER [Product-2] StorageProduct: Número de produtos que não foram consumidos no armazém Product-18: 4
Análise: Um armazém de produtos é estabelecido no método principal, e o armazém não associa 3 threads produtores e 4 threads de consumidores. Esses tópicos são iniciados para fazer com que o modelo de produtor/consumidor funcione. Quando o programa ocorre por 1600ms, todos os produtores param de produzir produtos e os consumidores param de consumir produtos.
O produto do thread do produtor produz um produto sem 300 ms no método de execução e o armazena no armazém; O consumidor de threads do consumidor pega um produto do armazém sem 500 ms no método de execução.
O armazém é responsável por armazenar e distribuir produtos. O método do StorageProduct é responsável por armazenar o produto. Quando o armazém está cheio, o thread atual entra em um estado de espera, ou seja, se o thread do produtor A chama o método do StorageProduct para armazenar o produto, ele constata que o armazém está cheio e não pode ser armazenado, ele entrará em um estado de espera. Quando o produto de armazenamento é bem -sucedido, o método Notify é chamado para acordar o tópico de consumidor em espera.
O método getProduct é responsável pelo produto com antecedência. Quando o armazém está vazio, o tópico atual entra em um estado de espera. Ou seja, se o thread do consumidor B chamar o método getProduct para obter o produto, ele descobrirá que o armazém está vazio, ele entrará em um estado de espera. Quando o produto é extraído com sucesso, o método Notify é chamado para acordar o thread do produtor em espera.
O artigo acima discute brevemente os problemas de produtores e consumidores nos threads java é todo o conteúdo que compartilho com você. Espero que possa lhe dar uma referência e espero que você possa apoiar mais o wulin.com.