๐ 1. Queue๋?
Queue๋ ์ปฌ๋ ์ ํ๋ ์์ํฌ์ ์ผ๋ถ๋ก, ๋ฐ์ดํฐ๋ฅผ ์ ์ ์ ์ถ(FIFO, First-In-First-Out) ๋ฐฉ์์ผ๋ก ์ ์ฅํ๊ณ ๊ด๋ฆฌํ๋ ์๋ฃ๊ตฌ์กฐ.
๐ 2. BlockingQueue๋?
Queue๋ฅผ ์์ ๋ฐ์, ํ์ ๊ธฐ๋ณธ์์ ์ ๋ธ๋กํน ์ฐ์ด ์ถ๊ฐ๋ ์ธํฐํ์ด์ค.
๋๊ธฐํ๋ ๋ฐฉ์์ผ๋ก ์๋ํ์ฌ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ์์ ํ๊ฒ ์ ๊ทผํ ์ ์๋ค.
BlockingQueue๋ ํ๊ฐ ๋น์ด ์์ ๋ ์์๋ฅผ ๊ฐ์ ธ์ค๋ ค๊ณ ํ๋ฉด ๋๊ธฐํ๊ณ , ํ๊ฐ ๊ฐ๋ ์ฐจ ์์ ๋ ์์๋ฅผ ์ถ๊ฐํ๋ ค๊ณ ํ๋ฉด ๋๊ธฐํ๋ค. (put, take ํจ์์์ ๋ธ๋ฝ๋์ ๋ ๋ค์ ์ฝ๋๊ฐ ์คํ๋์ง ์๊ณ ๋๊ธฐํ๋ ๊ฑธ ๋ณผ ์ ์๋ค!!)
*๋ธ๋กํน ์ฐ์ฐ
ํน์ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋ ๋๊น์ง ์ค๋ ๋๋ฅผ ์ผ์ ์ค์ง์ํค๋ ์ฐ์ฐ์ผ๋ก, ์ฐ์ฐ์ด ์๋ฃ๋ ๋๊น์ง ์ค๋ ๋๋ฅผ ๋๊ธฐ ์ํ๋ก ๋ง๋ ๋ค.
๐ 3. BlockingQueue์ ํน์ง
- ์ค๋ ๋ ์์ (Thread-safe): ๋ด๋ถ์์ lock์ผ๋ก ๋๊ธฐํํ์ฌ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋์์ ํ์ ์ ๊ทผํ๋๋ผ๋ ์์ ํ๊ฒ ์์ ์ ์ํํ ์ ์๋ค.
- ๋ธ๋กํน ์ฐ์ฐ: ํ๊ฐ ๊ฐ๋ ์ฐผ์ ๋์ put ์ฐ์ฐ๊ณผ ํ๊ฐ ๋น์์ ๋์ take ์ฐ์ฐ์ด ๋ธ๋กํน๋๋ค. ์ด๋ฌํ ์ฐ์ฐ๋ค์ ํน์ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋ ๋๊น์ง ์ค๋ ๋๋ฅผ ๋๊ธฐ(Block)์ํจ๋ค.
- ์๊ฐ์ ํ: offer(E e, long timeout, TimeUnit unit) ๋ฐ poll(long timeout, TimeUnit unit)๋ก ๋๊ธฐ ์๊ฐ์ ์ค์ ํ ์ ์๋ค. ์ง์ ๋ ์๊ฐ ๋ด์ ์ฐ์ฐ์ด ์๋ฃ๋์ง ์์ผ๋ฉด ํ์์์๊ณผ ํจ๊ป ์คํจํ๋ค.
๐ 4. BlockingQueue์ ์ฃผ์ ๋ฉ์๋
- put(E e): ์์๋ฅผ ํ์ ์ถ๊ฐ. ํ๊ฐ ๊ฐ๋ ์ฐจ ์์ผ๋ฉด ์์๋ฅผ ์ถ๊ฐํ ๋๊น์ง ๋ธ๋ก. (๋ฌดํ์ ๋๊ธฐ)
- offer(E e, long timeout, TimeUnit unit): ์์๋ฅผ ํ์ ์ถ๊ฐ. ํ๊ฐ ๊ฐ๋ ์ฐจ ์์ผ๋ฉด ์ง์ ๋ ์๊ฐ ๋์ ๋ธ๋ก. (timeOut ์๋ต ์ ์ฆ์ ์คํจ)
- take(): ํ์์ ์์๋ฅผ ์ ๊ฑฐํ๊ณ ๋ฐํํฉ๋๋ค. ํ๊ฐ ๋น์ด ์์ผ๋ฉด ์์๊ฐ ์ถ๊ฐ๋ ๋๊น์ง ๋ธ๋ก.
- poll(long timeout, TimeUnit unit): ํ์์ ์์๋ฅผ ์ ๊ฑฐํ๊ณ ๋ฐํ. ํ๊ฐ ๋น์ด ์์ผ๋ฉด ์ง์ ๋ ์๊ฐ ๋์ ๋ธ๋ก.
- remainingCapacity(): ํ์ ์ถ๊ฐํ ์ ์๋ ์์์ ์ต๋ ์๋ฅผ ๋ฐํ.
- size(): ํ์ ํ์ฌ ์ ์ฅ๋ ์์์ ์๋ฅผ ๋ฐํ.
- isEmpty(): ํ๊ฐ ๋น์ด ์๋์ง ํ์ธ.
๐ 5. BlockingQueue์ ๊ตฌํ์ฒด
โ 5-1. ArrayBlockingQueue
๊ณ ์ ํฌ๊ธฐ์ ๋ฐฐ์ด์ ๊ธฐ๋ฐ์ผ๋ก ํ ๊ตฌํ. ๊ตฌํ ์ ํฌ๊ธฐ๋ฅผ ์ง์ , ๋ณ๊ฒฝ ๋ถ๊ฐ.
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ArrayBlockingQueueExample {
public static void main(String[] args) throws InterruptedException {
BlockingQueue<String> queue = new ArrayBlockingQueue<>(3);
queue.put("first");
queue.put("second");
queue.put("third");
System.out.println(queue.take()); // ์ถ๋ ฅ: first
System.out.println(queue.peek()); // ์ถ๋ ฅ: second
}
}
โ 5-2. LinkedBlockingQueue
์ฐ๊ฒฐ ๋ ธ๋๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ ๊ตฌํ. ์ ํ์ ์ผ๋ก ์ต๋ ํฌ๊ธฐ๋ฅผ ์ค์ ํ ์ ์๋ค.
โญ ๊ฐ์ฅ ์ฝ๊ณ ๋ง์ด ์ฐ์ด๋ ํํ๋ผ๊ณ ํ๋ค!!
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class LinkedBlockingQueueExample {
public static void main(String[] args) throws InterruptedException {
BlockingQueue<String> queue = new LinkedBlockingQueue<>();
queue.put("first");
queue.put("second");
queue.put("third");
System.out.println(queue.take()); // ์ถ๋ ฅ: first
System.out.println(queue.peek()); // ์ถ๋ ฅ: second
}
}
โ 5-3. PriorityBlockingQueue
์์๋ฅผ ์ฐ์ ์์์ ๋ฐ๋ผ ์ ์ฅํ๋ ๊ตฌํ.
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class PriorityBlockingQueueExample {
public static void main(String[] args) throws InterruptedException {
BlockingQueue<Integer> queue = new PriorityBlockingQueue<>();
queue.put(3);
queue.put(1);
queue.put(2);
System.out.println(queue.take()); // ์ถ๋ ฅ: 1
System.out.println(queue.peek()); // ์ถ๋ ฅ: 2
}
}
โ 5-4. SynchronousQueue
๋ ์ค๋ ๋ ๊ฐ์ ์์๋ฅผ ์ง์ ์ ๋ฌํ๋ ๋๊ธฐํ๋ ํ. ์ด ํ๋ ๋ฒํผ๋ฅผ ๊ฐ์ง์ง ์๊ณ , ํ๋์ ์ค๋ ๋๊ฐ put() ๋ฉ์๋๋ก ์์๋ฅผ ์ถ๊ฐํ๋ฉด ๋ค๋ฅธ ์ค๋ ๋๋ ์ด ์์๋ฅผ take() ๋ฉ์๋๋ก ์ง์ ๋ฐ์์ผ ํ๋ค. ๋ฐ๋ผ์ ์์๋ฅผ ๋ฃ์ ๋๋ ๋ฐ๋์ ๋ค๋ฅธ ์ค๋ ๋๊ฐ ํด๋น ์์๋ฅผ ๋ฐ์ ๋๊น์ง ๋๊ธฐํ๋ค.
import java.util.concurrent.*;
public class SynchronousQueueExample {
public static void main(String[] args) {
// SynchronousQueue ์์ฑ
SynchronousQueue<String> queue = new SynchronousQueue<>();
// Producer ์ค๋ ๋ ์์ฑ
Thread producer = new Thread(() -> {
try {
String message = "Hello from producer!";
System.out.println("Producer is putting: " + message);
queue.put(message); // ์์ ์ถ๊ฐ (๋๊ธฐ์ํ๊ฐ ๋จ)
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// Consumer ์ค๋ ๋ ์์ฑ
Thread consumer = new Thread(() -> {
try {
String message = queue.take(); // ์์ ๊ฐ์ ธ์ค๊ธฐ (๋๊ธฐ์ํ๊ฐ ๋จ)
System.out.println("Consumer received: " + message);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// Producer์ Consumer ์ค๋ ๋ ์์
producer.start();
consumer.start();
}
}
๐ BlockingQueue์ ์ด์ฉํ ์์ฐ์-์๋น์ ํจํด
๐ ๋ธ๋ฝํนํ์ ์ฌ์ฉ ์์
์์ฐ์-์๋น์ ํจํด์ ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์ ์์์ ๊ณต์ ํ๋ ํ๋ก๊ทธ๋จ์ ๊ตฌํํ๋ ๋ฐ ์ฌ์ฉ๋๋ ์ผ๋ฐ์ ์ธ ๋์์ธ ํจํด ์ค ํ๋.
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class ProducerConsumerExample {
private static final int CAPACITY = 10;
private static final BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(CAPACITY);
public static void main(String[] args) {
Thread producerThread = new Thread(new Producer());
Thread consumerThread = new Thread(new Consumer());
producerThread.start();
consumerThread.start();
}
static class Producer implements Runnable {
@Override
public void run() {
try {
int value = 0;
while (true) {
queue.put(value);
System.out.println("Produced: " + value);
value++;
Thread.sleep(1000); // ์์ฐ ์๋ ์ ์ด
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class Consumer implements Runnable {
@Override
public void run() {
try {
while (true) {
int value = queue.take();
System.out.println("Consumed: " + value);
Thread.sleep(2000); // ์๋น ์๋ ์ ์ด
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
- ์์ฐ์ ์ค๋ ๋๋ 1์ด๋ง๋ค ํ์ ๊ฐ์ ๋ฃ๊ณ (put) ์์ฑ๋ ๊ฐ์ ์ถ๋ ฅ.
- ์๋น์ ์ค๋ ๋๋ 2์ด๋ง๋ค ํ์์ ๊ฐ์ ๊บผ๋ด์ด(take) ์๋นํ๊ณ ์ถ๋ ฅ.
- ์ด ๊ณผ์ ์์ BlockingQueue๋ ์์ฐ์์ ์๋น์ ๊ฐ์ ๋ฐ์ดํฐ ํ๋ฆ์ ์กฐ์จํ๊ณ ๋๊ธฐํํ๋ค. ๋ง์ฝ ํ๊ฐ ๋น์ด ์์ผ๋ฉด ์๋น์ ์ค๋ ๋๋ take() ๋ฉ์๋์์ ๋ธ๋ก๋์ด ๋๊ธฐํ๊ณ , ํ๊ฐ ๊ฐ๋ ์ฐจ ์์ผ๋ฉด ์์ฐ์ ์ค๋ ๋๋ put() ๋ฉ์๋์์ ๋ธ๋ก๋์ด ๋๊ธฐํ๊ฒ ๋๋ค.
'Backend > JAVA' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [Java] ๋น๋๊ธฐ ์์ ์ฒ๋ฆฌ (ExecutorService VS CompletableFuture) (0) | 2025.02.23 |
|---|---|
| HttpURLConnection (0) | 2024.06.07 |
| Callable, Runnable, Future (0) | 2024.06.05 |
| ์ค๋ ๋ ํ(Thread Pool), Executor (0) | 2024.06.05 |
| [Java] java.lang ํจํค์ง์ System (0) | 2023.10.12 |