LinkedBlockingQueue源码解读

502 阅读1分钟

基于LinkedBlocingQueue的生产者-消费者模式

class Test4{
    static LinkedBlockingQueue<Integer> linkedBlockingDeque = new LinkedBlockingQueue<>();
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(15);
        for(int i = 0; i < 8; i++){
            executorService.submit(new Product(linkedBlockingDeque));
        }

        for(int i = 0; i < 12; i++){
            executorService.submit(new Customer(linkedBlockingDeque));
        }
        executorService.shutdown();
    }
    static class Product implements Runnable{
        LinkedBlockingQueue<Integer> blockingQueue;
        Product(LinkedBlockingQueue<Integer> blockingQueue){
            this.blockingQueue = blockingQueue;
        }

        @Override
        public void run() {
            while (true){
                try {
                    int idx = new Random().nextInt();
                    blockingQueue.put(idx);
                    System.out.println(Thread.currentThread().getName() + "生产产品id:" + idx);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }

    static class Customer implements Runnable{
        LinkedBlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<>();
        Customer(LinkedBlockingQueue<Integer> blockingQueue){
            this.blockingQueue = blockingQueue;
        }
        @Override
        public void run() {
            while (true){
                try {
                    int idx = blockingQueue.take();
                    System.out.println(Thread.currentThread().getName() + "消费产品id:" + idx);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
}

添加

  1. public void put(E e) throws InterruptedException{};
  2. public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException{};

取出

  1. public E take() throws InterruptedException{};
  2. public E poll(long timeout, TimeUnit unit) throws InterruptedException{};

添加

put()

// 共享队列当前元素数量
private final AtomicInteger count = new AtomicInteger();
// 对put、offer加锁
private final ReentrantLock putLock = new ReentrantLock();
// 等待队列等待put
private final Condition notFull = putLock.newCondition();
public void put(E e) throws InterruptedException {
    if (e == null) throw new NullPointerException();
    // 使用一个负数进行标记失败,除非重新设置
    int c = -1;
    Node<E> node = new Node<E>(e);
    final ReentrantLock putLock = this.putLock;
    final AtomicInteger count = this.count; // CAS
    putLock.lockInterruptibly();
    try {
        // 容量满时,put开始等待
        while (count.get() == capacity) {
            notFull.await();
        }
        enqueue(node); // 操作:入队
        c = count.getAndIncrement();
        // 不为满时,唤醒put,可以继续put
        if (c + 1 < capacity)
            notFull.signal();
    } finally {
        putLock.unlock();
    }
    // 不为空,可以进行take
    if (c == 0)
        signalNotEmpty();
}

signalNotEmpty()方法

private void signalNotEmpty() {
    final ReentrantLock takeLock = this.takeLock;
    takeLock.lock();
    try {
        // 不为空,唤醒notEmpty线程,执行take
        notEmpty.signal();
    } finally {
        takeLock.unlock();
    }
}

取出

take()方法

public E take() throws InterruptedException {
    E x;
    int c = -1;
    final AtomicInteger count = this.count;
    final ReentrantLock takeLock = this.takeLock;
    takeLock.lockInterruptibly();
    try {
        while (count.get() == 0) {
            notEmpty.await();
        }
        x = dequeue();
        c = count.getAndDecrement();
        if (c > 1)
            notEmpty.signal();
    } finally {
        takeLock.unlock();
    }
    if (c == capacity)
        signalNotFull();
    return x;
}

signalNotEmpty()方法

private void signalNotFull() {
    final ReentrantLock putLock = this.putLock;
    putLock.lock();
    try {
        notFull.signal();
    } finally {
        putLock.unlock();
    }
}