LinkedBlockingQueue 原始碼解析

minororange發表於2021-11-17

BlockingQueue 介面定義

LinkedBlockingQueue 原始碼解析

對元素操作

丟擲異常 返回特殊值 阻塞 超時等待
插入 add(e) offer(e) put(e) offer(e,time,unit)
刪除 remove() poll() take() poll(time,unit)
檢查 element() peek() - -

LinkedBlockingQueue 原始碼

offer

    public boolean offer(E e) {
        // 如果元素為 null,丟擲 NullPointerException
        if (e == null) throw new NullPointerException();
        // 獲取當前佇列總數
        final AtomicInteger count = this.count;
        // 如果當前佇列總數達到最大值,直接返回 false (加入佇列失敗)
        if (count.get() == capacity)
            return false;
        // 初始化【佇列總數】,如果新增成功,c >=0 ,新增敗則為 -1
        int c = -1;
        // 將元素包裝成 Node
        Node<E> node = new Node<E>(e);
        // 獲取鎖物件(非公平鎖)
        final ReentrantLock putLock = this.putLock;
        // 加鎖
        putLock.lock();
        try {
            // 佇列總數小於最大值
            if (count.get() < capacity) {
               // 放入佇列,將佇列的【last】和 【last.next】賦值為 node
                enqueue(node);
                // 增加佇列總數,返回操作前的總數
                c = count.getAndIncrement();
                // 如果佇列總數 +1 沒超過最大值,傳送【佇列沒滿】的訊號,喚醒【寫入】的等待執行緒
                if (c + 1 < capacity)
                    notFull.signal();
            }
        } finally {
            // 釋放鎖
            putLock.unlock();
        }
        // 如果操作前佇列是空的,則傳送佇列不為空的訊號,喚醒【取出】的等待執行緒
        if (c == 0)
            signalNotEmpty();
        return c >= 0;
    }

put

 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;
        // 獲取鎖的過程中允許被中斷
        putLock.lockInterruptibly();
        try {
              // 當佇列滿的時候,進入等待,unsafe.park()
            while (count.get() == capacity) {
                notFull.await();
            }
            // 如果沒滿,則插入節點
            enqueue(node);
            c = count.getAndIncrement();
            if (c + 1 < capacity)
                notFull.signal();
        } finally {
            putLock.unlock();
        }
        if (c == 0)
            signalNotEmpty();
    }

take

 public E take() throws InterruptedException {
        // 初始化返回的變數
        E x;
        // 初始化【佇列總數】,如果取出成功,c >=0 ,取失敗則為 -1
        int c = -1;
        final AtomicInteger count = this.count;
        final ReentrantLock takeLock = this.takeLock;
        // 加鎖,允許被中斷
        takeLock.lockInterruptibly();
        try {
            // 當佇列為空時,掛起執行緒
            while (count.get() == 0) {
                notEmpty.await();
            }
            // 取出佇列第一個元素【head】,同時把head設為head.next
            x = dequeue();
            // 減少任務總數,並返回減少之前的總是
            c = count.getAndDecrement();
            // 如果之前的總數大於 1 ,則傳送不為空的訊號,喚醒【取】的執行緒
            if (c > 1)
                notEmpty.signal();
        } finally {
            // 釋放鎖
            takeLock.unlock();
        }
        // 如果取出之前的總數不為最大值,則傳送沒滿的訊號,喚醒【存】的執行緒
        if (c == capacity)
            signalNotFull();
        return x;
    }

poll

    public E poll() {
        final AtomicInteger count = this.count;
        // 任務總數為 0 直接返回null
        if (count.get() == 0)
            return null;
        E x = null;
        int c = -1;
        final ReentrantLock takeLock = this.takeLock;
        // 加鎖,不允許被中斷
        takeLock.lock();
        try {
            if (count.get() > 0) {
                x = dequeue();
                c = count.getAndDecrement();
                if (c > 1)
                    notEmpty.signal();
            }
        } finally {
            takeLock.unlock();
        }
        if (c == capacity)
            signalNotFull();
        return x;
    }

offer(e,timeout,unit)

     public boolean offer(E e, long timeout, TimeUnit unit)
        throws InterruptedException {

        if (e == null) throw new NullPointerException();
        // 轉換超時時間納秒
        long nanos = unit.toNanos(timeout);
        // 初始化【佇列總數】,如果新增成功,c >=0 ,新增敗則為 -1
        int c = -1;
        final ReentrantLock putLock = this.putLock;
        final AtomicInteger count = this.count;
        // 加鎖,允許被打斷
        putLock.lockInterruptibly();
        try {
            // 當佇列滿了的時候,觸發等待
            while (count.get() == capacity) {
                // 如果剩餘的等待時間小於等於0則返回false(新增失敗)
                if (nanos <= 0)
                    return false;
                // 返回剩餘的等待時間
                nanos = notFull.awaitNanos(nanos);
            }
            enqueue(new Node<E>(e));
            c = count.getAndIncrement();
            if (c + 1 < capacity)
                notFull.signal();
        } finally {
            putLock.unlock();
        }
        if (c == 0)
            signalNotEmpty();
        return true;
    }

poll(timeout,unit)

public E poll(long timeout, TimeUnit unit) throws InterruptedException {
        // 初始化返回元素
        E x = null;
        // 初始變化【取出】之前的任務總數,如果取出成功 c > 0 ,取出失敗則為 -1
        int c = -1;
        long nanos = unit.toNanos(timeout);
        final AtomicInteger count = this.count;
        final ReentrantLock takeLock = this.takeLock;
        // 加鎖,允許被打斷
        takeLock.lockInterruptibly();
        try {
            // 當任務佇列為空時,進入超時等待
            while (count.get() == 0) {
                // 剩餘等待時間 <=0 則返回 null
                if (nanos <= 0)
                    return null;
                // 返回剩餘等待時間
                nanos = notEmpty.awaitNanos(nanos);
            }
            x = dequeue();
            c = count.getAndDecrement();
            if (c > 1)
                notEmpty.signal();
        } finally {
            takeLock.unlock();
        }
        if (c == capacity)
            signalNotFull();
        return x;
    }
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章