Hoje vamos analisar o Java BlockingQueue. java.util.concurrent.BlockingQueue
é uma fila Java que suporta operações que esperam a fila ficar não vazia ao recuperar e remover um elemento, e espera que haja espaço disponível na fila ao adicionar um elemento.
Java BlockingQueue
A Java BlockingQueue não aceita valores
null
e lança NullPointerException
se você tentar armazenar um valor nulo na fila. As implementações da Java BlockingQueue são thread-safe. Todos os métodos de enfileiramento são atomicamente controlados 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 é principalmente usada para implementar o problema do produtor-consumidor. Não precisamos nos preocupar em esperar pelo espaço disponível para o produtor ou pelo objeto disponível para o consumidor na BlockingQueue, porque isso é tratado pelas classes de implementação da BlockingQueue. O 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 aguarda espaço ficar 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 a BlockingQueue do 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 Produtora 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 Consumidora que processará as mensagens da fila e encerrará 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;
//consumir 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, precisamos criar um serviço de BlockingQueue para produtor e consumidor. Este serviço produtor-consumidor criará a BlockingQueue com tamanho fixo e compartilhará com ambos produtores e consumidores. Este serviço iniciará as threads do produtor e do 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 Java Thread sleep é usado no produtor e consumidor para produzir e consumir mensagens com algum atraso.
Source:
https://www.digitalocean.com/community/tutorials/java-blockingqueue-example