Hoje vamos dar uma olhada em Java BlockingQueue. `java.util.concurrent.BlockingQueue
` é uma fila Java que suporta operações que esperam a fila se tornar não vazia ao recuperar e remover um elemento, e espera por espaço disponível na fila ao adicionar um elemento.
Java BlockingQueue
Java BlockingQueue não aceita valores
null
e lança NullPointerException
se você tentar armazenar um valor nulo na fila. As implementações de Java BlockingQueue são thread-safe. Todos os métodos de enfileiramento são atômicos por natureza e usam bloqueios internos ou outras formas de controle de concorrência. A interface Java BlockingQueue faz parte do framework de coleções Java e é usada principalmente para implementar o problema do produtor-consumidor. Não precisamos nos preocupar em esperar pelo espaço estar disponível para o produtor ou o objeto estar disponível para o consumidor na BlockingQueue porque isso é tratado pelas classes de implementação de BlockingQueue. Java fornece várias implementações de BlockingQueue, como ArrayBlockingQueue
, LinkedBlockingQueue
, PriorityBlockingQueue
, SynchronousQueue
etc. Ao implementar o problema do produtor-consumidor em BlockingQueue, usaremos a implementação ArrayBlockingQueue. Aqui estão alguns métodos importantes que você deve conhecer.
put(E e)
: Este método é usado para inserir elementos na fila. Se a fila estiver cheia, ele espera que o espaço esteja disponível.E take()
: This method retrieves and remove the element from the head of the queue. If queue is empty it waits for the element to be available.
Vamos implementar o problema do produtor-consumidor usando BlockingQueue em Java agora.
Exemplo de BlockingQueue em Java – Mensagem
Apenas um objeto Java normal que será produzido pelo Produtor e adicionado à fila. Você também pode chamá-lo de carga útil ou mensagem da fila.
package com.journaldev.concurrency;
public class Message {
private String msg;
public Message(String str){
this.msg=str;
}
public String getMsg() {
return msg;
}
}
Exemplo de BlockingQueue em Java – Produtor
Classe Produtor que criará mensagens e as colocará na fila.
package com.journaldev.concurrency;
import java.util.concurrent.BlockingQueue;
public class Producer implements Runnable {
private BlockingQueue queue;
public Producer(BlockingQueue q){
this.queue=q;
}
@Override
public void run() {
// produzir mensagens
for(int i=0; i<100; i++){
Message msg = new Message(""+i);
try {
Thread.sleep(i);
queue.put(msg);
System.out.println("Produced "+msg.getMsg());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// adicionando mensagem de saída
Message msg = new Message("exit");
try {
queue.put(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Exemplo de BlockingQueue em Java – Consumidor
Classe Consumidor que processará as mensagens da fila e terminará quando receber a mensagem de saída.
package com.journaldev.concurrency;
import java.util.concurrent.BlockingQueue;
public class Consumer implements Runnable{
private BlockingQueue queue;
public Consumer(BlockingQueue q){
this.queue=q;
}
@Override
public void run() {
try{
Message msg;
// consumindo mensagens até receber a mensagem de saída
while((msg = queue.take()).getMsg() !="exit"){
Thread.sleep(10);
System.out.println("Consumed "+msg.getMsg());
}
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
Exemplo de BlockingQueue em Java – Serviço
Finalmente, temos que criar um serviço BlockingQueue para produtor e consumidor. Este serviço de produtor e consumidor criará a BlockingQueue com tamanho fixo e a compartilhará com ambos produtores e consumidores. Este serviço iniciará threads de produtor e consumidor e sairá.
package com.journaldev.concurrency;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ProducerConsumerService {
public static void main(String[] args) {
//Criando BlockingQueue de tamanho 10
BlockingQueue queue = new ArrayBlockingQueue<>(10);
Producer producer = new Producer(queue);
Consumer consumer = new Consumer(queue);
//iniciando produtor para produzir mensagens na fila
new Thread(producer).start();
//iniciando consumidor para consumir mensagens da fila
new Thread(consumer).start();
System.out.println("Producer and Consumer has been started");
}
}
A saída do exemplo de programa Java BlockingQueue acima é mostrada abaixo.
Producer and Consumer has been started
Produced 0
Produced 1
Produced 2
Produced 3
Produced 4
Consumed 0
Produced 5
Consumed 1
Produced 6
Produced 7
Consumed 2
Produced 8
...
O sono da Thread Java é usado no produtor e no consumidor para produzir e consumir mensagens com algum atraso.
Source:
https://www.digitalocean.com/community/tutorials/java-blockingqueue-example