1 7 8 package java.util.concurrent; 9 import java.util.*; 10 import java.util.concurrent.atomic.*; 11 12 13 50 public class ConcurrentLinkedQueue<E> extends AbstractQueue<E> 51 implements Queue<E>, java.io.Serializable { 52 private static final long serialVersionUID = 196745693267521676L; 53 54 63 64 private static class Node<E> { 65 private volatile E item; 66 private volatile Node<E> next; 67 68 private static final 69 AtomicReferenceFieldUpdater<Node, Node> 70 nextUpdater = 71 AtomicReferenceFieldUpdater.newUpdater 72 (Node.class, Node.class, "next"); 73 private static final 74 AtomicReferenceFieldUpdater<Node, Object > 75 itemUpdater = 76 AtomicReferenceFieldUpdater.newUpdater 77 (Node.class, Object .class, "item"); 78 79 Node(E x) { item = x; } 80 81 Node(E x, Node<E> n) { item = x; next = n; } 82 83 E getItem() { 84 return item; 85 } 86 87 boolean casItem(E cmp, E val) { 88 return itemUpdater.compareAndSet(this, cmp, val); 89 } 90 91 void setItem(E val) { 92 itemUpdater.set(this, val); 93 } 94 95 Node<E> getNext() { 96 return next; 97 } 98 99 boolean casNext(Node<E> cmp, Node<E> val) { 100 return nextUpdater.compareAndSet(this, cmp, val); 101 } 102 103 void setNext(Node<E> val) { 104 nextUpdater.set(this, val); 105 } 106 107 } 108 109 private static final 110 AtomicReferenceFieldUpdater<ConcurrentLinkedQueue , Node> 111 tailUpdater = 112 AtomicReferenceFieldUpdater.newUpdater 113 (ConcurrentLinkedQueue .class, Node.class, "tail"); 114 private static final 115 AtomicReferenceFieldUpdater<ConcurrentLinkedQueue , Node> 116 headUpdater = 117 AtomicReferenceFieldUpdater.newUpdater 118 (ConcurrentLinkedQueue .class, Node.class, "head"); 119 120 private boolean casTail(Node<E> cmp, Node<E> val) { 121 return tailUpdater.compareAndSet(this, cmp, val); 122 } 123 124 private boolean casHead(Node<E> cmp, Node<E> val) { 125 return headUpdater.compareAndSet(this, cmp, val); 126 } 127 128 129 133 private transient volatile Node<E> head = new Node<E>(null, null); 134 135 136 private transient volatile Node<E> tail = head; 137 138 139 142 public ConcurrentLinkedQueue() {} 143 144 152 public ConcurrentLinkedQueue(Collection<? extends E> c) { 153 for (Iterator<? extends E> it = c.iterator(); it.hasNext();) 154 add(it.next()); 155 } 156 157 159 167 public boolean add(E o) { 168 return offer(o); 169 } 170 171 179 public boolean offer(E o) { 180 if (o == null) throw new NullPointerException (); 181 Node<E> n = new Node<E>(o, null); 182 for(;;) { 183 Node<E> t = tail; 184 Node<E> s = t.getNext(); 185 if (t == tail) { 186 if (s == null) { 187 if (t.casNext(s, n)) { 188 casTail(t, n); 189 return true; 190 } 191 } else { 192 casTail(t, s); 193 } 194 } 195 } 196 } 197 198 public E poll() { 199 for (;;) { 200 Node<E> h = head; 201 Node<E> t = tail; 202 Node<E> first = h.getNext(); 203 if (h == head) { 204 if (h == t) { 205 if (first == null) 206 return null; 207 else 208 casTail(t, first); 209 } else if (casHead(h, first)) { 210 E item = first.getItem(); 211 if (item != null) { 212 first.setItem(null); 213 return item; 214 } 215 } 217 } 218 } 219 } 220 221 public E peek() { for (;;) { 223 Node<E> h = head; 224 Node<E> t = tail; 225 Node<E> first = h.getNext(); 226 if (h == head) { 227 if (h == t) { 228 if (first == null) 229 return null; 230 else 231 casTail(t, first); 232 } else { 233 E item = first.getItem(); 234 if (item != null) 235 return item; 236 else casHead(h, first); 238 } 239 } 240 } 241 } 242 243 249 Node<E> first() { 250 for (;;) { 251 Node<E> h = head; 252 Node<E> t = tail; 253 Node<E> first = h.getNext(); 254 if (h == head) { 255 if (h == t) { 256 if (first == null) 257 return null; 258 else 259 casTail(t, first); 260 } else { 261 if (first.getItem() != null) 262 return first; 263 else casHead(h, first); 265 } 266 } 267 } 268 } 269 270 271 public boolean isEmpty() { 272 return first() == null; 273 } 274 275 287 public int size() { 288 int count = 0; 289 for (Node<E> p = first(); p != null; p = p.getNext()) { 290 if (p.getItem() != null) { 291 if (++count == Integer.MAX_VALUE) 293 break; 294 } 295 } 296 return count; 297 } 298 299 public boolean contains(Object o) { 300 if (o == null) return false; 301 for (Node<E> p = first(); p != null; p = p.getNext()) { 302 E item = p.getItem(); 303 if (item != null && 304 o.equals(item)) 305 return true; 306 } 307 return false; 308 } 309 310 public boolean remove(Object o) { 311 if (o == null) return false; 312 for (Node<E> p = first(); p != null; p = p.getNext()) { 313 E item = p.getItem(); 314 if (item != null && 315 o.equals(item) && 316 p.casItem(item, null)) 317 return true; 318 } 319 return false; 320 } 321 322 public Object [] toArray() { 323 ArrayList<E> al = new ArrayList<E>(); 325 for (Node<E> p = first(); p != null; p = p.getNext()) { 326 E item = p.getItem(); 327 if (item != null) 328 al.add(item); 329 } 330 return al.toArray(); 331 } 332 333 public <T> T[] toArray(T[] a) { 334 int k = 0; 336 Node<E> p; 337 for (p = first(); p != null && k < a.length; p = p.getNext()) { 338 E item = p.getItem(); 339 if (item != null) 340 a[k++] = (T)item; 341 } 342 if (p == null) { 343 if (k < a.length) 344 a[k] = null; 345 return a; 346 } 347 348 ArrayList<E> al = new ArrayList<E>(); 350 for (Node<E> q = first(); q != null; q = q.getNext()) { 351 E item = q.getItem(); 352 if (item != null) 353 al.add(item); 354 } 355 return (T[])al.toArray(a); 356 } 357 358 368 public Iterator<E> iterator() { 369 return new Itr(); 370 } 371 372 private class Itr implements Iterator<E> { 373 376 private Node<E> nextNode; 377 378 384 private E nextItem; 385 386 389 private Node<E> lastRet; 390 391 Itr() { 392 advance(); 393 } 394 395 399 private E advance() { 400 lastRet = nextNode; 401 E x = nextItem; 402 403 Node<E> p = (nextNode == null)? first() : nextNode.getNext(); 404 for (;;) { 405 if (p == null) { 406 nextNode = null; 407 nextItem = null; 408 return x; 409 } 410 E item = p.getItem(); 411 if (item != null) { 412 nextNode = p; 413 nextItem = item; 414 return x; 415 } else p = p.getNext(); 417 } 418 } 419 420 public boolean hasNext() { 421 return nextNode != null; 422 } 423 424 public E next() { 425 if (nextNode == null) throw new NoSuchElementException(); 426 return advance(); 427 } 428 429 public void remove() { 430 Node<E> l = lastRet; 431 if (l == null) throw new IllegalStateException (); 432 l.setItem(null); 434 lastRet = null; 435 } 436 } 437 438 445 private void writeObject(java.io.ObjectOutputStream s) 446 throws java.io.IOException { 447 448 s.defaultWriteObject(); 450 451 for (Node<E> p = first(); p != null; p = p.getNext()) { 453 Object item = p.getItem(); 454 if (item != null) 455 s.writeObject(item); 456 } 457 458 s.writeObject(null); 460 } 461 462 467 private void readObject(java.io.ObjectInputStream s) 468 throws java.io.IOException , ClassNotFoundException { 469 s.defaultReadObject(); 471 head = new Node<E>(null, null); 472 tail = head; 473 for (;;) { 475 E item = (E)s.readObject(); 476 if (item == null) 477 break; 478 else 479 offer(item); 480 } 481 } 482 483 } 484 | Popular Tags |