天天看點

LinkedBlockingQueue阻塞隊列offer()操作抛出中斷異常

說明

在使用LinkedBlockingQueue的offer方法時,出現了中斷異常,現分析一下出現這個中斷異常的原因。

會産生中斷異常的Demo

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

public class TestLinkedBlockingQueue {

    public static void main(String[] args) {
        LinkedBlockingQueue lbq = new LinkedBlockingQueue(3);
        for(int i = 0; i < 10; i++){
            try {
                System.out.println(lbq);
                //這裡用offer方法往阻塞隊列裡面添加對象,此方法表示若隊列滿了,則等待1秒,1秒後若隊列還是滿的,則丢棄資料。
                lbq.offer(i, 1000, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            Thread.currentThread().interrupt();//如果注釋掉這行代碼,則此程式不會抛出異常
        }
    }
}           

LinkedBlockingQueue的offer源碼方法

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

        if (e == null) throw new NullPointerException();
        long nanos = unit.toNanos(timeout);
        int c = -1;
        final ReentrantLock putLock = this.putLock;
        final AtomicInteger count = this.count;
        putLock.lockInterruptibly();
        try {
            while (count.get() == capacity) {
                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;
    }

    
    //lockInterruptibly方法
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }
    //acquireInterruptibly方法
        public final void acquireInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        if (!tryAcquire(arg))
            doAcquireInterruptibly(arg);
    }           

是以,當線程被标記有中斷标志時,offer添加時将擷取不到鎖,直接抛出中斷異常。

繼續閱讀