b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

链表 结构 解读 Java 并发队列 BlockingQueue(6)

电脑杂谈  发布时间:2018-02-21 23:42:01  来源:网络整理

接下来,我们来看看具体的源码实现吧,它的源码不是很简单的那种,我们需要先搞清楚它的设计思想。

源码加注释大概有 1200 行,我们先看大框架:

// 构造时,我们可以指定公平模式还是非公平模式,区别之后再说

public SynchronousQueue(boolean fair) {

transferer = fair ? new TransferQueue() : new TransferStack();

}

abstract static class Transferer {

// 从方法名上大概就知道,这个方法用于转移元素,从生产者手上转到消费者手上

// 也可以被动地,消费者调用这个方法来从生产者手上取元素

// 第一个参数 e 如果不是 null,代表场景为:将元素从生产者转移给消费者

二叉链表定义_数据结构_链表 结构

// 如果是 null,代表消费者等待生产者提供元素,然后返回值就是相应的生产者提供的元素

// 第二个参数代表是否设置超时,如果设置超时,超时时间是第三个参数的值

// 返回值如果是 null,代表超时,或者中断。具体是哪个,可以通过检测中断状态得到。

abstract Object transfer(Object e, boolean timed, long nanos);

}

Transferer 有两个内部实现类,是因为构造 SynchronousQueue 的时候,我们可以指定公平策略。公平模式意味着,所有的读写线程都遵守先来后到,FIFO 嘛,对应 TransferQueue。而非公平模式则对应 TransferStack。

我们先采用公平模式分析源码,然后再说说公平模式和非公平模式的区别。

接下来,我们看看 put 方法和 take 方法:

// 写入值

public void put(E o) throws InterruptedException {

if (o == null) throw new NullPointerException();

if (transferer.transfer(o, false, 0) == null) { // 1

Thread.interrupted();

throw new InterruptedException();

}

}

// 读取值并移除

public E take() throws InterruptedException {

Object e = transferer.transfer(null, false, 0); // 2

if (e != null)

return (E)e;

Thread.interrupted();

throw new InterruptedException();

}

我们看到,写操作 put(E o) 和读操作 take() 都是调用 Transferer.transfer(…) 方法,区别在于第一个参数是否为 null 值。

我们来看看 transfer 的设计思路,其基本算法如下:

当调用这个方法时,如果队列是空的,或者队列中的节点和当前的线程操作类型一致(如当前操作是 put 操作,而队列中的元素也都是写线程)。这种情况下,将当前线程加入到等待队列即可。

如果队列中有等待节点,而且与当前操作可以匹配(如队列中都是读操作线程,当前线程是写操作线程,反之亦然)。这种情况下,匹配等待队列的队头,出队,返回相应数据。

其实这里有个隐含的条件被满足了,队列如果不为空,肯定都是同种类型的节点,要么都是读操作,要么都是写操作。这个就要看到底是读线程积压了,还是写线程积压了。


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-87792-6.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    • 王宇帅
      王宇帅

      我怎么感觉你是来秀优越感的呢

    热点图片
    拼命载入中...