Implementação do Problema do Produtor-Consumidor com Wait-Notify

Abordagem usando wait-notify:

A classe Buffer implementa o armaeznamento de itens produzidos, controlando operações de inserção e remoção.

import java.util.LinkedList;

import static java.lang.Thread.sleep;

public class Buffer {
    private final int CAPACIDADE_MAXIMA = 10;
    private LinkedList<Object> itens = new LinkedList<>();

    /**
     * @param valor Identificador do produto a ser produzido
     * @param tempo Tempo necessário para produção em segundos
     */
    public void produzir(int valor, int tempo) {
        synchronized (itens) {
            while (itens.size() == CAPACIDADE_MAXIMA) {
                System.out.println("Armazém cheio (" + CAPACIDADE_MAXIMA + " itens). Não é possível adicionar mais.");
                try {
                    wait();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
            itens.add(valor);
            try {
                sleep(tempo * 1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                System.out.println("Tempo de produção: " + tempo + " segundos");
            }
            System.out.println("Produtor " + Thread.currentThread().getName() + " adicionou item. Total: " + itens.size());
            System.out.println("----------------------------------------");
            itens.notifyAll();
        }
    }

    /**
     * Método correspondente à operação de consumo
     * @param tempo Tempo necessário para consumo em segundos
     */
    public void consumir(int tempo) {
        synchronized (itens) {
            while (itens.isEmpty()) {
                System.out.println("Nenhum item no armazém. Aguardando produção...");
                try {
                    wait();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
            itens.removeFirst();
            try {
                sleep(tempo * 1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                System.out.println("Tempo de consumo: " + tempo + " segundos");
            }
            System.out.println("Consumidor " + Thread.currentThread().getName() + " removeu item. Total: " + itens.size());
            System.out.println("----------------------------------------");
            itens.notifyAll();
        }
    }
}

BufferA classe Producer executa a operação de produção:

public class Produtor implements Runnable {
    private Buffer buffer;
    private String nomeProdutor;

    public Produtor(Buffer buffer) {
        this.buffer = buffer;
    }

    public String getNomeProdutor() {
        return nomeProdutor;
    }

    public void setNomeProdutor(String nomeProdutor) {
        this.nomeProdutor = nomeProdutor;
    }

    @Override
    public void run() {
        buffer.produzir((int)(Math.random() * 10), (int)(Math.random() * 10));
    }
}

ProdutorA classe Consumer realiza a operação de consumo:

public class Consumidor implements Runnable {
    private Buffer buffer;
    private String nomeConsumidor;

    public Consumidor(Buffer buffer) {
        this.buffer = buffer;
    }

    public String getNomeConsumidor() {
        return nomeConsumidor;
    }

    public void setNomeConsumidor(String nomeConsumidor) {
        this.nomeConsumidor = nomeConsumidor;
    }

    @Override
    public void run() {
        buffer.consumir((int)(Math.random() * 10));
    }
}

ConsumidorA classe Teste contém o método principal para testar a funcionalidade:

public class Teste {
    public static void main(String[] args) {
        Buffer buffer = new Buffer();
        
        Thread produtor1 = new Thread(new Produtor(buffer));
        Thread produtor2 = new Thread(new Produtor(buffer));
        Thread produtor3 = new Thread(new Produtor(buffer));
        Thread produtor4 = new Thread(new Produtor(buffer));

        Thread consumidor1 = new Thread(new Consumidor(buffer));
        Thread consumidor2 = new Thread(new Consumidor(buffer));
        Thread consumidor3 = new Thread(new Consumidor(buffer));
        Thread consumidor4 = new Thread(new Consumidor(buffer));

        produtor1.start();
        produtor2.start();
        produtor3.start();
        produtor4.start();

        consumidor1.start();
        consumidor2.start();
        consumidor3.start();
        consumidor4.start();
    }
}

Teste

Tags: java thread Sincronização produtor-consumidor wait-notify

Publicado em 9-12 23:45