오늘은 Java BlockingQueue에 대해 알아보겠습니다. java.util.concurrent.BlockingQueue
는 요소를 검색하고 제거할 때 큐가 비어있지 않을 때까지 대기하며, 요소를 추가할 때 큐에 공간이 사용 가능해질 때까지 대기하는 작업을 지원하는 자바 큐입니다.
Java BlockingQueue
Java BlockingQueue는
null
값을 허용하지 않으며, 큐에 null 값을 저장하려고하면 NullPointerException
을 throw합니다. Java BlockingQueue 구현은 스레드 안전합니다. 모든 큐 메서드는 원자적인 성격을 가지며, 내부 잠금이나 다른 형태의 동시성 제어를 사용합니다. Java BlockingQueue 인터페이스는 Java 컬렉션 프레임워크의 일부이며, 주로 생산자 소비자 문제를 구현하는 데 사용됩니다. BlockingQueue에서 생산자나 객체를 기다리는 것에 대해 걱정할 필요가 없습니다. 이는 BlockingQueue의 구현 클래스에서 처리됩니다. Java는 ArrayBlockingQueue
, LinkedBlockingQueue
, PriorityBlockingQueue
, SynchronousQueue
등 여러 가지 BlockingQueue 구현을 제공합니다. BlockingQueue에서 생산자 소비자 문제를 구현할 때는 ArrayBlockingQueue 구현을 사용합니다. 다음은 알아야 할 중요한 메서드 몇 가지입니다.
put(E e)
: 이 메서드는 요소를 큐에 삽입하는 데 사용됩니다. 큐가 가득 찬 경우, 공간이 사용 가능하게 될 때까지 대기합니다.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.
이제 자바 BlockingQueue를 사용하여 생산자 소비자 문제를 구현해 보겠습니다.
자바 BlockingQueue 예제 – 메시지
생산자에 의해 생성되고 큐에 추가되는 일반적인 자바 객체입니다. 이를 payload 또는 큐 메시지로도 부를 수 있습니다.
package com.journaldev.concurrency;
public class Message {
private String msg;
public Message(String str){
this.msg=str;
}
public String getMsg() {
return msg;
}
}
자바 BlockingQueue 예제 – 생산자
메시지를 생성하고 큐에 넣는 Producer 클래스입니다.
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() {
// 메시지 생성
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();
}
}
// 종료 메시지 추가
Message msg = new Message("exit");
try {
queue.put(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
자바 BlockingQueue 예제 – 소비자
큐에서 메시지를 처리하고 종료 메시지를 수신하면 종료되는 Consumer 클래스입니다.
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;
// 종료 메시지를 받을 때까지 메시지 소비
while((msg = queue.take()).getMsg() !="exit"){
Thread.sleep(10);
System.out.println("Consumed "+msg.getMsg());
}
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
Java BlockingQueue 예제 – 서비스
마침내 우리는 생산자와 소비자를위한 BlockingQueue 서비스를 생성해야합니다. 이 생산자 소비자 서비스는 고정 크기의 BlockingQueue를 생성하고 생성자와 소비자 모두와 공유할 것입니다. 이 서비스는 생성자 및 소비자 스레드를 시작하고 종료될 것입니다.
package com.journaldev.concurrency;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ProducerConsumerService {
public static void main(String[] args) {
//크기가 10 인 BlockingQueue 생성
BlockingQueue queue = new ArrayBlockingQueue<>(10);
Producer producer = new Producer(queue);
Consumer consumer = new Consumer(queue);
//생산자를 시작하여 대기열에 메시지를 생성합니다
new Thread(producer).start();
//소비자를 시작하여 대기열에서 메시지를 소비합니다
new Thread(consumer).start();
System.out.println("Producer and Consumer has been started");
}
}
위의 java BlockingQueue 예제 프로그램의 출력은 아래에 표시됩니다.
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
...
Java 스레드 슬립은 생산자와 소비자에서 일정한 지연으로 메시지를 생성하고 소비하는 데 사용됩니다.
Source:
https://www.digitalocean.com/community/tutorials/java-blockingqueue-example