Finalmente entender completamente! Uma compreensão gráfica do caso Java multi-threaded de produtores e consumidores de padrões de projeto

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;
Aqui Insert Picture Descrição
 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 é ArrayListo 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 synchronizedmodificaçã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;

Aqui Insert Picture Descrição

á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

Aqui Insert Picture Descrição
 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!

Publicado 84 artigos originais · Louvor obteve 126 · vista 120 000 +

Acho que você gosta

Origin blog.csdn.net/qq_44717317/article/details/104884787
Recomendado
Clasificación