生产者-消费者模式
实现一
通过一个阻塞队列来实现生产者-消费者模式,生产者将数据放入队列中,消费者从队列中取出数据进行处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public class ProducerConsumerBQ { private static final BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(5);
public static void main(String[] args) { new Thread(() -> { try { for(int i = 1; i < 10; i ++) { queue.put(i); System.out.println("producer -> {}" + i); Thread.sleep(500); } } catch (InterruptedException e) { e.printStackTrace(); } }, "Producer").start();
new Thread(() -> { try { while(true) { Integer item = queue.take(); System.out.println("consumer -> {}" + item); Thread.sleep(1000); } } catch(InterruptedException e) { e.printStackTrace(); } }, "consumer").start(); } }
|
实现二
通过自定义一个阻塞队列来实现生产者-消费者模式
- 一个锁来保证线程安全
- 两个
Condition 变量来实现生产者和消费者的等待和唤醒机制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
| import java.util.ArrayDeque; import java.util.Deque; import java.util.Objects; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock;
public class ProducerConsumerBQ {
static class BlockingQueue<T> { private final Deque<T> deque = new ArrayDeque<>(); private final int capacity; private final ReentrantLock lock = new ReentrantLock();
private final Condition notEmpty = lock.newCondition(); private final Condition notFull = lock.newCondition();
private boolean closed = false;
public BlockingQueue(int capacity) { if (capacity <= 0) { throw new IllegalArgumentException("capacity must be > 0"); } this.capacity = capacity; }
public void put(T element) throws InterruptedException { Objects.requireNonNull(element, "element cannot be null"); lock.lockInterruptibly(); try { while (deque.size() == capacity) { if (closed) { throw new IllegalStateException("queue is closed"); } notFull.await(); }
if (closed) { throw new IllegalStateException("queue is closed"); }
deque.addLast(element); notEmpty.signal(); } finally { lock.unlock(); } }
public T take() throws InterruptedException { lock.lockInterruptibly(); try { while (deque.isEmpty()) { if (closed) { return null; } notEmpty.await(); }
T value = deque.removeFirst(); notFull.signal(); return value; } finally { lock.unlock(); } }
public void close() { lock.lock(); try { closed = true; notEmpty.signalAll(); notFull.signalAll(); } finally { lock.unlock(); } } }
public static void main(String[] args) throws InterruptedException { BlockingQueue<String> bq = new BlockingQueue<>(3);
Thread producer = new Thread(() -> { try { for (int i = 0; i < 10; i++) { Thread.sleep(1000); String item = String.valueOf(i); bq.put(item); System.out.println("生产: " + item); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.out.println("生产者被中断,停止生产"); } finally { bq.close(); System.out.println("生产者结束,队列已关闭"); } }, "producer");
Thread consumer = new Thread(() -> { try { while (true) { String item = bq.take(); if (item == null) { System.out.println("队列已关闭且无数据,消费者退出"); break; } System.out.println("消费: " + item); Thread.sleep(3000); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.out.println("消费者被中断,停止消费"); } }, "consumer");
producer.start(); consumer.start();
producer.join(); consumer.join(); System.out.println("主线程结束"); } }
|