java源码分析

来源:互联网 发布:怎么在淘宝里卖二东西 编辑:程序博客网 时间:2024/06/05 09:00

arrayBlockQueue

生成(插入元素)

在往队列中插入数据由下面几个函数,他们的区别就是对队列满的情况处理不同
- put 一直等待着
- offer(无时间) 如果空了直接返回false
- offer(有时间) 等待指定的时间,在指定时间内如果空了,那么插入,负责返回false
- add 抛出一个IllegalStateException异常

首先来看put实现

   public void put(E e) throws InterruptedException {        checkNotNull(e);        final ReentrantLock lock = this.lock;        lock.lockInterruptibly();        try {            while (count == items.length)                notFull.await();            insert(e);        } finally {            lock.unlock();        }    }

首先需要获取锁,并把锁设置成可中断的。 然后判断是不是有空闲(count == items.length表示满了),如果没有空闲的空间,就通过await()一直等待着。 一直到有空闲了,通过insert进行插入。因为使用了可重入的锁,需要unlock解锁

然后我们来看下insert的实现

    private void insert(E x) {        items[putIndex] = x;        putIndex = inc(putIndex);        ++count;        notEmpty.signal();    }

把元素放到队列的最后面,对应的下标+1,数量也+1,最后通过signal通知其他线程有空闲的了

再来看下offer(无时间的)

    public boolean offer(E e) {        checkNotNull(e);        final ReentrantLock lock = this.lock;        lock.lock();        try {            if (count == items.length)                return false;            else {                insert(e);                return true;            }        } finally {            lock.unlock();        }    }

很简单,就看是否有空,没有空的直接返回false,否则就插入并返回true

然后来看看有时间版本的offer

    public boolean offer(E e, long timeout, TimeUnit unit)        throws InterruptedException {        checkNotNull(e);        long nanos = unit.toNanos(timeout);        final ReentrantLock lock = this.lock;        lock.lockInterruptibly();        try {            while (count == items.length) {                if (nanos <= 0)                    return false;                nanos = notFull.awaitNanos(nanos);            }            insert(e);            return true;        } finally {            lock.unlock();        }    }

当没有空间的时候,就等待指定的时间,如果等待时间到了还没有空,返回false,否则就插入并返回true

消费(移除元素)

同样消费也有好几个版本的,他们的区别也都是对队列是空的情况的处理
- take
- poll(有时间)
- poll(没有时间)

我们看下take

    public E take() throws InterruptedException {        final ReentrantLock lock = this.lock;        lock.lockInterruptibly();        try {            while (count == 0)                notEmpty.await();            return extract();        } finally {            lock.unlock();        }    }

如果队列是空的,那么一直等着,知道有元素可以消费,然后调用extract进行消费,同样最后需要释放锁
我们在看下extract的实现

    private E extract() {        final Object[] items = this.items;        E x = this.<E>cast(items[takeIndex]);        items[takeIndex] = null;        takeIndex = inc(takeIndex);        --count;        notFull.signal();        return x;    }

把队列尾部的数据拿出来,尾部往前面挪动下,数据-1,最后通知其他线程队列有空的了

然后看下没有时间版本的poll

   public E poll() {        final ReentrantLock lock = this.lock;        lock.lock();        try {            return (count == 0) ? null : extract();        } finally {            lock.unlock();        }    }

如果空的,就直接但会空的了

有时间版本的poll

    public E poll(long timeout, TimeUnit unit) throws InterruptedException {        long nanos = unit.toNanos(timeout);        final ReentrantLock lock = this.lock;        lock.lockInterruptibly();        try {            while (count == 0) {                if (nanos <= 0)                    return null;                nanos = notEmpty.awaitNanos(nanos);            }            return extract();        } finally {            lock.unlock();        }    }

这个如果是空的,那么就等待设置的时间,时间到了还没有就返回空的

其他操作

0 0