Produtores e consumidores
Antes de sugestões de leitura
Se o papel precisa ter uma compreensão mais profunda das recomendações olhar thread-safe, impasses de rosca, e comunicação do conhecimento-thread relacionado, se você já tem conhecimento suficiente desses, eu acredito que você deve ler este gratificante blogue!
compreensão aprofundada dos tópicos Java - Bancos me deve quatro milhões! ! !
Ilustração de um minuto do impasse thread Java com uma história de ninar
Em primeiro lugar, a cena do projeto
Existente duas roscas, a rosca é uma série de caracteres efeito 'A' 'B' 'C ' 'D' 'E' ou 'F' 'L' 'H ' 'I' 'J' na lista de matriz recipiente ( ), mas, a fim de garantir a segurança do thread, você só pode fazer um acesso fio, de modo que cada segmento deve adquirir o bloqueio para o objeto de recurso crítico que é rotulado recipiente para acessar o objeto, em seguida, executar operações de armazenamento de dados;
no entanto, cada fio de cada cinco vezes o número de caracteres armazenados, e o recipiente só pode ser armazenado em quatro cadeias, em que o quinto segmento corda para dentro do recipiente, para evitar processos anormais, o segmento irá aguardar indefinidamente na fila, e notificar o acesso aos consumidores de dados;
da mesma forma, uma pluralidade de consumidores, mas também ter acesso aos dados qualificar marca de bloqueio, assumindo um consumidor consumer
, os consumidores o acesso aos dados, tira uma hipótese, quando o recipiente quando os dados foram tomadas a fim de garantir o fio de segurança, o segmento irá aguardar indefinidamente na fila, e notificar o produtor dos dados armazenados;
todo o processo é padrões de design de rosca java entre produtores e consumidores;
Em segundo lugar, a introdução de produtores e consumidores
Você primeiro precisa entender a natureza dos produtores e consumidores são thread, um número de produtores na produção de produtos que estarão disponíveis para tirar uma série de gastos do consumidor, a fim de tornar os produtores e consumidoresexecução simultâneaEntre os dois conjuntos de um tampão capaz de armazenar uma pluralidade de produtos, os produtores irá produzir o produto para o buffer, produtos de consumo removido da memória intermédia para o consumo, obviamente, deve situar-se entre os produtores e consumidores para manter o ritmo, não só não permitir aos consumidores um produto de remoção de tampão vazios, mas também permitir que o produtor para adicionar produtos a um buffer cheio.
Em terceiro lugar, o código reprodução cenário
Em primeiro lugar, a necessidade de criar uma classe de recipiente Queue
, a capacidade máxima do recipiente 4, o tipo é ArrayList
o tipo de recipiente fornece dois métodos, um método é armazenado offer()
, fornecida para as chamadas de rosca produtor; Outro método consiste em remover poll()
, para as chamadas de rosca consumidor ; para atender manter a sincronização entre produtores e consumidores, cada método deve fazer três coisas:
- 1. Para garantir a segurança do thread, deve ser bloqueado recipiente, que só pode fazer a thread que acesso tag bloqueio; Neste método requer uma
synchronized
modificação; - 2. Quando o recipiente é vez cheio ou vazio (tamanho == 0 ou tamanho == 4), o segmento correspondente para os consumidores ou de rosca consumidor espera indefinidamente, chamando o
wait()
método; - Ou inferior a 3. Quando o recipiente não estiver vazio, o consumidor correspondente notificação acrescentou produtores para produzir, um consumidor produtor notificação correspondente gastos removidos;
área de memória tampão de dados de simulação
//我的队列
class MyQueue {
private List values = new ArrayList();
private int max = 4;
//存入队列
public synchronized void offer(Object o){//E
while(values.size() == max){
//进来线程,停下
try {
this.wait();
//被唤醒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();
values.add(o);
System.out.println(Thread.currentThread().getName() + "存入元素 : "+ values );
}
//从队列取出
public synchronized Object poll(){//1个元素
while(values.size() == 0){
try {
this.wait();
//被唤醒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();//唤醒因mq对象而进入无限期等待的线程对象(一个)
return values.remove(0);
}
}
simulação de produtores
O produtor é essencialmente um fio aqui usa dois produtores, ou seja, acesso multi-threaded, um objeto de recurso crítico Queue
, apenas a thread que a marca de bloqueio quando o objeto pode acessar o objeto, em seguida, a ação apropriada.
//生产者1
class Produce1 extends Thread{
MyQueue mq;
public Produce1(MyQueue mq){
this.mq = mq;
}
public void run(){
System.out.println("Produce1启动");
for (char ch = 'A'; ch <= 'E'; ch++) {
mq.offer(ch);
}
System.out.println("Produce1结束");
}
}
//生产者2
class Produce2 extends Thread{
MyQueue mq;
public Produce2(MyQueue mq){
this.mq = mq;
}
public void run(){
System.out.println("Produce2启动");
for (char ch = 'F'; ch <= 'J'; ch++) {
mq.offer(ch);
}
System.out.println("Produce2结束");
}
}
simulação de consumidores
Os consumidores também uma discussão sobre a natureza, é claro, os consumidores podem ter os mesmos produtores como múltiplas, similar, somente aqueles com os segmentos de consumo marcado com bloqueio tem o direito de operar objeto de recurso crítico; Por conveniência, considere um consumidor;
//消费者
class Consumer extends Thread{
MyQueue mq;
public Consumer(MyQueue mq){
this.mq = mq;
}
public void run(){
for (int i = 0 ; i < 10 ; i++) {//循环取数据
System.out.println(mq.poll() + "被移除");
}
}
}
A função principal
A função principal é deixar os tópicos iniciados pode ser!
public static void main(String[] args) {
MyQueue mq = new MyQueue();
Produce1 p1 = new Produce1(mq);
Produce2 p2 = new Produce2(mq);
Consumer c1 = new Consumer(mq);
p1.start();
p2.start();
c1.start();
System.out.println("main end");
}
resultados operacionais
Claramente imprimir os resultados têm sido muito claro ao longo do processo nos diz que consumidores e produtores a execução simultânea, acredito que sua mente formou uma imagem animada, eu espero que você entenda que há ajuda! Claro, se conveniente, por favor, incentivar seus polegares! Seja grato!