ArrayBlockQueue的put方法源码阅读

ArrayBlockingQueue使用示例

package queue;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ArrayBlockingQueueTest {
    /**
     * 创建容量大小为1的有界队列
     */
    private BlockingQueue<queue.Ball> blockingQueue = new ArrayBlockingQueue<Ball>(1);

    /**
     * 队列大小
     * @return
     */
    public int queueSize(){
        return blockingQueue.size();
    }

    /**
     * 将球放入队列当中,生产者
     * @param ball
     * @throws InterruptedException
     */
    public void produce(Ball ball) throws InterruptedException{
        blockingQueue.put(ball);
    }

    /**
     * 将球从队列当中拿出去,消费者
     * @return
     */
    public Ball consume() throws InterruptedException {
       return blockingQueue.take();
    }

    public static void main(String[] args){
        final ArrayBlockingQueueTest box = new ArrayBlockingQueueTest();
        ExecutorService executorService = Executors.newCachedThreadPool();

        /**
         * 往箱子里面放入乒乓球
         */
        executorService.submit(new Runnable() {
            public void run() {
                int i = 0;
                for(int j=0;j<10;j++){
                    Ball ball = new Ball();
                    ball.setNumber("乒乓球编号:"+i);
                    ball.setColor("yellow");
                    try {
                        long man=System.currentTimeMillis();
                        System.out.println(man +
                                ":准备往箱子里放入乒乓球:--->" + ball.getNumber());
                        box.produce(ball);
                        System.out.println(man +
                                ":往箱子里放入乒乓球:--->" + ball.getNumber());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    i++;
                }
            }
        });

        /**
         * consumer,负责从箱子里面拿球出来
         */
        executorService.submit(new Runnable() {
            public void run() {
                for(int i=0;i<10;i++){
                    try {
                        long man=System.currentTimeMillis();
                        System.out.println(man +
                                "准备到箱子中拿乒乓球:--->");
                        Ball ball = box.consume();
                        System.out.println(man +
                                "拿到箱子中的乒乓球:--->" + ball.getNumber());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

    }

}

构造函数

capacity:队列的大小(items数组的长度),fair:为false时reentrantLock为非公平锁,为true时为公平锁

public ArrayBlockingQueue(int capacity) {
    this(capacity, false);
}
public ArrayBlockingQueue(int capacity, boolean fair) {
    if (capacity <= 0)
        throw new IllegalArgumentException();
    this.items = new Object[capacity];
    lock = new ReentrantLock(fair);
    notEmpty = lock.newCondition();
    notFull =  lock.newCondition();
}
//将集合c中的元素存到ArrayBlockingQueue中
public ArrayBlockingQueue(int capacity, boolean fair,
                          Collection<? extends E> c){
                          ...
}

ArrayBlockingQueue的属性

  • final Object[] items : 保存放入队列中的元素
  • int takeIndex :下一次使用 take、poll、peek或者remove方法时操作的元素的索引
  • int putIndex : 下一次使用put、offer或者add方法时添加的元素在items中的索引
  • int count :items中储存的元素的数量
  • final ReentranLock lock
  • private final Condition notEmpty:Condition for waiting takes
  • private final Condition notFull:Condition for waiting puts

put()

在BlockingQueue接口中申明

/**
*将指定的元素插入队列,队列中没有空间时会进行等待
*/
void put(E e) throws InterruptedException;

在ArrayBlockingQueue中的实现

/**
*将指定的元素插入到队列的队尾,当队列满了后将等待空间提供
*/
public void put(E e) throws InterruptedException {
    Objects.requireNonNull(e);
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        while (count == items.length)
            notFull.await();
        enqueue(e);
    } finally {
        lock.unlock();
    }
}
requireNonNull()

Objects类中定义的静态方法:检查指定的Object是否为null

public static <T> T requireNonNull(T obj) {
    if (obj == null)
        throw new NullPointerException();
    return obj;
}
await()

在Condition接口中定义:让当前线程进行等待,直到收到信号或者被中断

/**
 * Causes the current thread to wait until it is signalled or
 * {@linkplain Thread#interrupt interrupted}.
 */
void await() throws InterruptedException;

在AbstractQueueSynchronizer中实现:实现可中断条件等待

/**
 * Implements interruptible condition wait.
 * <ol>
 * <li>If current thread is interrupted, throw InterruptedException.
 * <li>Save lock state returned by {@link #getState}.
 * <li>Invoke {@link #release} with saved state as argument,
 *     throwing IllegalMonitorStateException if it fails.
 * <li>Block until signalled or interrupted.
 * <li>Reacquire by invoking specialized version of
 *     {@link #acquire} with saved state as argument.
 * <li>If interrupted while blocked in step 4, throw InterruptedException.
 * </ol>
 */
public final void await() throws InterruptedException {
    if (Thread.interrupted())
        throw new InterruptedException();
    Node node = addConditionWaiter();
    int savedState = fullyRelease(node);//释放全部的独占锁,如果节点失效,将节点的ws设置为cancelled
    int interruptMode = 0;
    //判断条件队列中的node是否在同步队列中
    while (!isOnSyncQueue(node)) {
        LockSupport.park(this);//阻塞当前线程
        if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
            break;
    }
    //走到这里说明节点已经条件满足被加入到了同步队列或者中断了
    if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
        interruptMode = REINTERRUPT;
        //走到这里说明已经成功获取了独占锁,
        //删除条件队列中被取消的节点
    if (node.nextWaiter != null) // clean up if cancelled
        unlinkCancelledWaiters();
        //等于0是唤醒返回,非正常中断方式中,抛出异常,如果是中断之后在被唤醒,线程进行自我中断
    if (interruptMode != 0)
        reportInterruptAfterWait(interruptMode);
}
addConditionWaiter()

将新的等待线程加入到等待队列中

/**
 * Adds a new waiter to wait queue.
 * @return its new wait node
 */
private Node addConditionWaiter() {
    if (!isHeldExclusively())//判断当前线程是否独占锁 getExclusiveOwnerThread() == Thread.currentThread()
        throw new IllegalMonitorStateException();
    Node t = lastWaiter;
    // If lastWaiter is cancelled, clean out.
    //等待队列中的node的waitStatus只有Condition和cancelled两种状态
    if (t != null && t.waitStatus != Node.CONDITION) {
        unlinkCancelledWaiters();//删除等待队列中waitStatus!=Node.CONDITION的节点
        t = lastWaiter;
    }
    /**
    *Node(int waitStatus) {
    *	WAITSTATUS.set(this, waitStatus);
    *	THREAD.set(this, Thread.currentThread());  
    */}
    Node node = new Node(Node.CONDITION);

    if (t == null)
        firstWaiter = node;
    else
        t.nextWaiter = node;
    lastWaiter = node;
    return node;
}
fullConditionWaiter()
/**
 * Invokes release with current state value; returns saved state.
 * Cancels node and throws exception on failure.
 * @param node the condition node for this wait
 * @return previous sync state
 */
final int fullyRelease(Node node) {
    try {
        int savedState = getState();//得到当前独占锁的加锁次数
        if (release(savedState))//一次性全部释放
            return savedState;
        throw new IllegalMonitorStateException();
    } catch (Throwable t) {
    	//失败时将node的waitStatus设置为Node.CANCELLED,标记该节点已失效
        node.waitStatus = Node.CANCELLED;
        throw t;
    }
}
isOnSynQueue()

判断在条件队列中的节点现在是否在同步队列中等待被释放
虽然同步队列和条件队列都是使用AQS中的Node类来实现的,但是同步队列是双向链表,使用Node类中的next和prev属性;条件队列是单项链表,使用Node类中的nextWaiter属性,

/**
 * Returns true if a node, always one that was initially placed on
 * a condition queue, is now waiting to reacquire on sync queue.
 * @param node the node
 * @return true if is reacquiring
 */
final boolean isOnSyncQueue(Node node) {
    if (node.waitStatus == Node.CONDITION || node.prev == null)
        return false;
    if (node.next != null) // If has successor, it must be on queue
        return true;
    /*
     * node.prev can be non-null, but not yet on queue because
     * the CAS to place it on queue can fail. So we have to
     * traverse from tail to make sure it actually made it.  It
     * will always be near the tail in calls to this method, and
     * unless the CAS failed (which is unlikely), it will be
     * there, so we hardly ever traverse much.
     */
     //在队列中从后往前遍历,判断node是否在同步队列中存在
    return findNodeFromTail(node);
}
checkInterruptWhileWaiting()
/**
 * Checks for interrupt, returning THROW_IE if interrupted
 * before signalled, REINTERRUPT if after signalled, or
 * 0 if not interrupted.
 */
private int checkInterruptWhileWaiting(Node node) {
    return Thread.interrupted() ?
        (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
        0;//
}
final boolean transferAfterCancelledWait(Node node) {
	//将node的ws设置为初始值:0,设置为0是进入同步队列的先决条件,
    if (node.compareAndSetWaitStatus(Node.CONDITION, 0)) {
        enq(node);//将node加入同步队列
        /**
        *private Node enq(Node node) {
	*    for (;;) {
	*        Node oldTail = tail;
	*        if (oldTail != null) {
	*            node.setPrevRelaxed(oldTail);
	*            if (compareAndSetTail(oldTail, node)) {
	*                oldTail.next = node;
	*                return oldTail;
	*            }
	*        } else {
	*            initializeSyncQueue();
	*        }
	*   }
	*}
	*/
	return true;
    }
    // 判断是否在同步队列中,否则让此线程处于一直让渡资源
    while (!isOnSyncQueue(node))
    //Thread.yield()方法作用是:暂停当前正在执行的线程对象(及放弃当前拥有的cup资源),并执行其他线程。
        Thread.yield();
    return false;
}
unlinkCancelledWaiters()

从条件队列中删除waitStatus!=Condition的节点

private void unlinkCancelledWaiters() {
    Node t = firstWaiter;
    Node trail = null;
    while (t != null) {
        Node next = t.nextWaiter;
        if (t.waitStatus != Node.CONDITION) {
            t.nextWaiter = null;
            if (trail == null)
                firstWaiter = next;
            else
                trail.nextWaiter = next;
            if (next == null)
                lastWaiter = trail;
        }
        else
            trail = t;
        t = next;
    }
}
reportInterruptAfterWait()
/**
 * Throws InterruptedException, reinterrupts current thread, or
 * does nothing, depending on mode.
 */
private void reportInterruptAfterWait(int interruptMode)
    throws InterruptedException {
    if (interruptMode == THROW_IE)
        throw new InterruptedException();
    else if (interruptMode == REINTERRUPT)
        selfInterrupt();
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HashMap 是 JDK 中提供的一个哈希表实现类,其底层实现使用数组+链表(或红黑树)的方式实现。下面是 HashMap 中 put() 和 get() 方法源码分析: 1. put() 方法源码: ```java public V put(K key, V value) { // 计算 key 的哈希值 int hash = hash(key); // 根据哈希值计算数组下标 int i = indexFor(hash, table.length); // 如果该位置还没有元素,则直接将新元素插入 for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; // 如果 key 已经存在,则替换原有的值 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } // 如果该位置已经有元素,则将新元素插入链表头部 modCount++; addEntry(hash, key, value, i); return null; } ``` 2. get() 方法源码: ```java public V get(Object key) { if (key == null) return getForNullKey(); // 计算 key 的哈希值 int hash = hash(key); // 根据哈希值计算数组下标 for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) { Object k; // 如果 key 已经存在,则返回对应的值 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) return e.value; } // 如果 key 不存在,则返回 null return null; } ``` 可以看出,put() 方法先根据 key 的哈希值计算数组下标,然后遍历该位置的链表,如果找到了已经存在的 key,则替换对应的 value,如果没有找到,则将新元素插入链表头部。get() 方法也是先根据 key 的哈希值计算数组下标,然后遍历该位置的链表,如果找到了已经存在的 key,则返回对应的 value,如果没有找到,则返回 null。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值