-
Notifications
You must be signed in to change notification settings - Fork 32
/
LinkedBlockingDeque 源码解析.md
236 lines (184 loc) · 4.99 KB
/
LinkedBlockingDeque 源码解析.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
#### LinkedBlockingDeque
* 实现接口 BlockingDeque,而 BlockingDeque 又继承接口 BlockingQueue ,提供了一系列的以First和Last结尾的方法,如addFirst、addLast、peekFirst、peekLast,为双向操作Queue提供了可能。
* 底层实现就是链表,然后用 Lock 加锁,维护了头节点和尾节点
* LinkedBlockingQueue 介绍省略
##### 属性
```java
public class LinkedBlockingDeque<E>
extends AbstractQueue<E>
implements BlockingDeque<E>, java.io.Serializable {
// 双向链表的表头
transient Node<E> first;
// 双向链表的表尾
transient Node<E> last;
// 大小,双向链表中当前节点个数
private transient int count;
// 容量,在创建LinkedBlockingDeque时指定的
private final int capacity;
final ReentrantLock lock = new ReentrantLock();
private final Condition notEmpty = lock.newCondition();
private final Condition notFull = lock.newCondition();
static final class Node<E> {
E item;
Node<E> prev;
Node<E> next;
Node(E x) { item = x; }
}
}
```
##### 基础方法
* LinkedBlockingDeque 的add、put、offer、take、peek、poll系列方法都是通过调用XXXFirst,XXXLast方法。
* 这里就仅以putFirst、putLast、takeFirst、takeLast分析下。 offer 和 poll 的不超时实际就是比 put 和 take 在失败时不会用 Codition 等待,offer 和 poll 的超时实际就是 Codition 等待加个超时时间而已
###### putFirst
```java
public void putFirst(E e) throws InterruptedException {
// check null
if (e == null) throw new NullPointerException();
Node<E> node = new Node<E>(e);
// 获取锁
final ReentrantLock lock = this.lock;
lock.lock();
try {
while (!linkFirst(node))
// 在notFull条件上等待,直到被唤醒或中断
notFull.await();
} finally {
// 释放锁
lock.unlock();
}
}
private boolean linkFirst(Node<E> node) {
// 超出容量
if (count >= capacity)
return false;
// 首节点
Node<E> f = first;
// 新节点的next指向原first
node.next = f;
// 设置node为新的first
first = node;
// 没有尾节点,设置node为尾节点
if (last == null)
last = node;
// 有尾节点,那就将之前first的pre指向新增node
else
f.prev = node;
++count;
// 唤醒notEmpty
notEmpty.signal();
return true;
}
```
###### **putLast**
```java
public void putLast(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
Node<E> node = new Node<E>(e);
final ReentrantLock lock = this.lock;
lock.lock();
try {
while (!linkLast(node))
notFull.await();
} finally {
lock.unlock();
}
}
private boolean linkLast(Node<E> node) {
if (count >= capacity)
return false;
// 尾节点
Node<E> l = last;
// 将Node的前驱指向原本的last
node.prev = l;
// 将node设置为last
last = node;
// 首节点为null,则设置node为first
if (first == null)
first = node;
else
//非null,说明之前的last有值,就将之前的last的next指向node
l.next = node;
++count;
notEmpty.signal();
return true;
}
```
###### takeFirst
```java
public E takeFirst() throws InterruptedException {
final ReentrantLock lock = this.lock;
// 获取锁
lock.lock();
try {
E x;
// 尝试出队
while ( (x = unlinkFirst()) == null)
// 失败阻塞
notEmpty.await();
return x;
} finally {
// 释放锁
lock.unlock();
}
}
private E unlinkFirst() {
// 首节点
Node<E> f = first;
// 空队列,直接返回null
if (f == null)
return null;
// first.next
Node<E> n = f.next;
// 节点item
E item = f.item;
// 移除掉first ==> first = first.next
f.item = null;
f.next = f; // help GC
first = n;
// 移除后为空队列,仅有一个节点
if (n == null)
last = null;
else
// n的pre原来指向之前的first,现在n变为first了,pre指向null
n.prev = null;
--count;
notFull.signal();
return item;
```
###### takeLast
````java
public E takeLast() throws InterruptedException {
final ReentrantLock lock = this.lock;
// 获取锁
lock.lock();
try {
E x;
// 尝试出队
while ( (x = unlinkLast()) == null)
// 失败阻塞
notEmpty.await();
return x;
} finally {
// 释放锁
lock.unlock();
}
}
private E unlinkLast() {
// assert lock.isHeldByCurrentThread();
Node<E> l = last;
if (l == null)
return null;
Node<E> p = l.prev;
E item = l.item;
l.item = null;
l.prev = l; // help GC
last = p;
if (p == null)
first = null;
else
p.next = null;
--count;
notFull.signal();
return item;
}
````