1 7 8 package java.util.concurrent; 9 import java.util.*; 10 import java.util.concurrent.locks.*; 11 12 41 public class LinkedBlockingDeque<E> 42 extends AbstractQueue<E> 43 implements BlockingDeque <E>, java.io.Serializable { 44 45 49 50 56 57 private static final long serialVersionUID = -387911632671998426L; 58 59 60 static final class Node<E> { 61 E item; 62 Node<E> prev; 63 Node<E> next; 64 Node(E x, Node<E> p, Node<E> n) { 65 item = x; 66 prev = p; 67 next = n; 68 } 69 } 70 71 72 private transient Node<E> first; 73 74 private transient Node<E> last; 75 76 private transient int count; 77 78 private final int capacity; 79 80 private final ReentrantLock lock = new ReentrantLock(); 81 82 private final Condition notEmpty = lock.newCondition(); 83 84 private final Condition notFull = lock.newCondition(); 85 86 90 public LinkedBlockingDeque() { 91 this(Integer.MAX_VALUE); 92 } 93 94 100 public LinkedBlockingDeque(int capacity) { 101 if (capacity <= 0) throw new IllegalArgumentException (); 102 this.capacity = capacity; 103 } 104 105 115 public LinkedBlockingDeque(Collection<? extends E> c) { 116 this(Integer.MAX_VALUE); 117 for (E e : c) 118 add(e); 119 } 120 121 122 124 127 private boolean linkFirst(E e) { 128 if (count >= capacity) 129 return false; 130 ++count; 131 Node<E> f = first; 132 Node<E> x = new Node<E>(e, null, f); 133 first = x; 134 if (last == null) 135 last = x; 136 else 137 f.prev = x; 138 notEmpty.signal(); 139 return true; 140 } 141 142 145 private boolean linkLast(E e) { 146 if (count >= capacity) 147 return false; 148 ++count; 149 Node<E> l = last; 150 Node<E> x = new Node<E>(e, l, null); 151 last = x; 152 if (first == null) 153 first = x; 154 else 155 l.next = x; 156 notEmpty.signal(); 157 return true; 158 } 159 160 163 private E unlinkFirst() { 164 Node<E> f = first; 165 if (f == null) 166 return null; 167 Node<E> n = f.next; 168 first = n; 169 if (n == null) 170 last = null; 171 else 172 n.prev = null; 173 --count; 174 notFull.signal(); 175 return f.item; 176 } 177 178 181 private E unlinkLast() { 182 Node<E> l = last; 183 if (l == null) 184 return null; 185 Node<E> p = l.prev; 186 last = p; 187 if (p == null) 188 first = null; 189 else 190 p.next = null; 191 --count; 192 notFull.signal(); 193 return l.item; 194 } 195 196 199 private void unlink(Node<E> x) { 200 Node<E> p = x.prev; 201 Node<E> n = x.next; 202 if (p == null) { 203 if (n == null) 204 first = last = null; 205 else { 206 n.prev = null; 207 first = n; 208 } 209 } else if (n == null) { 210 p.next = null; 211 last = p; 212 } else { 213 p.next = n; 214 n.prev = p; 215 } 216 --count; 217 notFull.signalAll(); 218 } 219 220 222 226 public void addFirst(E e) { 227 if (!offerFirst(e)) 228 throw new IllegalStateException ("Deque full"); 229 } 230 231 235 public void addLast(E e) { 236 if (!offerLast(e)) 237 throw new IllegalStateException ("Deque full"); 238 } 239 240 243 public boolean offerFirst(E e) { 244 if (e == null) throw new NullPointerException (); 245 lock.lock(); 246 try { 247 return linkFirst(e); 248 } finally { 249 lock.unlock(); 250 } 251 } 252 253 256 public boolean offerLast(E e) { 257 if (e == null) throw new NullPointerException (); 258 lock.lock(); 259 try { 260 return linkLast(e); 261 } finally { 262 lock.unlock(); 263 } 264 } 265 266 270 public void putFirst(E e) throws InterruptedException { 271 if (e == null) throw new NullPointerException (); 272 lock.lock(); 273 try { 274 while (!linkFirst(e)) 275 notFull.await(); 276 } finally { 277 lock.unlock(); 278 } 279 } 280 281 285 public void putLast(E e) throws InterruptedException { 286 if (e == null) throw new NullPointerException (); 287 lock.lock(); 288 try { 289 while (!linkLast(e)) 290 notFull.await(); 291 } finally { 292 lock.unlock(); 293 } 294 } 295 296 300 public boolean offerFirst(E e, long timeout, TimeUnit unit) 301 throws InterruptedException { 302 if (e == null) throw new NullPointerException (); 303 long nanos = unit.toNanos(timeout); 304 lock.lockInterruptibly(); 305 try { 306 for (;;) { 307 if (linkFirst(e)) 308 return true; 309 if (nanos <= 0) 310 return false; 311 nanos = notFull.awaitNanos(nanos); 312 } 313 } finally { 314 lock.unlock(); 315 } 316 } 317 318 322 public boolean offerLast(E e, long timeout, TimeUnit unit) 323 throws InterruptedException { 324 if (e == null) throw new NullPointerException (); 325 long nanos = unit.toNanos(timeout); 326 lock.lockInterruptibly(); 327 try { 328 for (;;) { 329 if (linkLast(e)) 330 return true; 331 if (nanos <= 0) 332 return false; 333 nanos = notFull.awaitNanos(nanos); 334 } 335 } finally { 336 lock.unlock(); 337 } 338 } 339 340 343 public E removeFirst() { 344 E x = pollFirst(); 345 if (x == null) throw new NoSuchElementException(); 346 return x; 347 } 348 349 352 public E removeLast() { 353 E x = pollLast(); 354 if (x == null) throw new NoSuchElementException(); 355 return x; 356 } 357 358 public E pollFirst() { 359 lock.lock(); 360 try { 361 return unlinkFirst(); 362 } finally { 363 lock.unlock(); 364 } 365 } 366 367 public E pollLast() { 368 lock.lock(); 369 try { 370 return unlinkLast(); 371 } finally { 372 lock.unlock(); 373 } 374 } 375 376 public E takeFirst() throws InterruptedException { 377 lock.lock(); 378 try { 379 E x; 380 while ( (x = unlinkFirst()) == null) 381 notEmpty.await(); 382 return x; 383 } finally { 384 lock.unlock(); 385 } 386 } 387 388 public E takeLast() throws InterruptedException { 389 lock.lock(); 390 try { 391 E x; 392 while ( (x = unlinkLast()) == null) 393 notEmpty.await(); 394 return x; 395 } finally { 396 lock.unlock(); 397 } 398 } 399 400 public E pollFirst(long timeout, TimeUnit unit) 401 throws InterruptedException { 402 long nanos = unit.toNanos(timeout); 403 lock.lockInterruptibly(); 404 try { 405 for (;;) { 406 E x = unlinkFirst(); 407 if (x != null) 408 return x; 409 if (nanos <= 0) 410 return null; 411 nanos = notEmpty.awaitNanos(nanos); 412 } 413 } finally { 414 lock.unlock(); 415 } 416 } 417 418 public E pollLast(long timeout, TimeUnit unit) 419 throws InterruptedException { 420 long nanos = unit.toNanos(timeout); 421 lock.lockInterruptibly(); 422 try { 423 for (;;) { 424 E x = unlinkLast(); 425 if (x != null) 426 return x; 427 if (nanos <= 0) 428 return null; 429 nanos = notEmpty.awaitNanos(nanos); 430 } 431 } finally { 432 lock.unlock(); 433 } 434 } 435 436 439 public E getFirst() { 440 E x = peekFirst(); 441 if (x == null) throw new NoSuchElementException(); 442 return x; 443 } 444 445 448 public E getLast() { 449 E x = peekLast(); 450 if (x == null) throw new NoSuchElementException(); 451 return x; 452 } 453 454 public E peekFirst() { 455 lock.lock(); 456 try { 457 return (first == null) ? null : first.item; 458 } finally { 459 lock.unlock(); 460 } 461 } 462 463 public E peekLast() { 464 lock.lock(); 465 try { 466 return (last == null) ? null : last.item; 467 } finally { 468 lock.unlock(); 469 } 470 } 471 472 public boolean removeFirstOccurrence(Object o) { 473 if (o == null) return false; 474 lock.lock(); 475 try { 476 for (Node<E> p = first; p != null; p = p.next) { 477 if (o.equals(p.item)) { 478 unlink(p); 479 return true; 480 } 481 } 482 return false; 483 } finally { 484 lock.unlock(); 485 } 486 } 487 488 public boolean removeLastOccurrence(Object o) { 489 if (o == null) return false; 490 lock.lock(); 491 try { 492 for (Node<E> p = last; p != null; p = p.prev) { 493 if (o.equals(p.item)) { 494 unlink(p); 495 return true; 496 } 497 } 498 return false; 499 } finally { 500 lock.unlock(); 501 } 502 } 503 504 506 517 public boolean add(E e) { 518 addLast(e); 519 return true; 520 } 521 522 525 public boolean offer(E e) { 526 return offerLast(e); 527 } 528 529 533 public void put(E e) throws InterruptedException { 534 putLast(e); 535 } 536 537 541 public boolean offer(E e, long timeout, TimeUnit unit) 542 throws InterruptedException { 543 return offerLast(e, timeout, unit); 544 } 545 546 556 public E remove() { 557 return removeFirst(); 558 } 559 560 public E poll() { 561 return pollFirst(); 562 } 563 564 public E take() throws InterruptedException { 565 return takeFirst(); 566 } 567 568 public E poll(long timeout, TimeUnit unit) throws InterruptedException { 569 return pollFirst(timeout, unit); 570 } 571 572 582 public E element() { 583 return getFirst(); 584 } 585 586 public E peek() { 587 return peekFirst(); 588 } 589 590 601 public int remainingCapacity() { 602 lock.lock(); 603 try { 604 return capacity - count; 605 } finally { 606 lock.unlock(); 607 } 608 } 609 610 616 public int drainTo(Collection<? super E> c) { 617 if (c == null) 618 throw new NullPointerException (); 619 if (c == this) 620 throw new IllegalArgumentException (); 621 lock.lock(); 622 try { 623 for (Node<E> p = first; p != null; p = p.next) 624 c.add(p.item); 625 int n = count; 626 count = 0; 627 first = last = null; 628 notFull.signalAll(); 629 return n; 630 } finally { 631 lock.unlock(); 632 } 633 } 634 635 641 public int drainTo(Collection<? super E> c, int maxElements) { 642 if (c == null) 643 throw new NullPointerException (); 644 if (c == this) 645 throw new IllegalArgumentException (); 646 lock.lock(); 647 try { 648 int n = 0; 649 while (n < maxElements && first != null) { 650 c.add(first.item); 651 first.prev = null; 652 first = first.next; 653 --count; 654 ++n; 655 } 656 if (first == null) 657 last = null; 658 notFull.signalAll(); 659 return n; 660 } finally { 661 lock.unlock(); 662 } 663 } 664 665 667 671 public void push(E e) { 672 addFirst(e); 673 } 674 675 678 public E pop() { 679 return removeFirst(); 680 } 681 682 684 698 public boolean remove(Object o) { 699 return removeFirstOccurrence(o); 700 } 701 702 707 public int size() { 708 lock.lock(); 709 try { 710 return count; 711 } finally { 712 lock.unlock(); 713 } 714 } 715 716 724 public boolean contains(Object o) { 725 if (o == null) return false; 726 lock.lock(); 727 try { 728 for (Node<E> p = first; p != null; p = p.next) 729 if (o.equals(p.item)) 730 return true; 731 return false; 732 } finally { 733 lock.unlock(); 734 } 735 } 736 737 741 boolean removeNode(Node<E> e) { 742 lock.lock(); 743 try { 744 for (Node<E> p = first; p != null; p = p.next) { 745 if (p == e) { 746 unlink(p); 747 return true; 748 } 749 } 750 return false; 751 } finally { 752 lock.unlock(); 753 } 754 } 755 756 769 public Object [] toArray() { 770 lock.lock(); 771 try { 772 Object [] a = new Object [count]; 773 int k = 0; 774 for (Node<E> p = first; p != null; p = p.next) 775 a[k++] = p.item; 776 return a; 777 } finally { 778 lock.unlock(); 779 } 780 } 781 782 818 public <T> T[] toArray(T[] a) { 819 lock.lock(); 820 try { 821 if (a.length < count) 822 a = (T[])java.lang.reflect.Array.newInstance( 823 a.getClass().getComponentType(), 824 count 825 ); 826 827 int k = 0; 828 for (Node<E> p = first; p != null; p = p.next) 829 a[k++] = (T)p.item; 830 if (a.length > k) 831 a[k] = null; 832 return a; 833 } finally { 834 lock.unlock(); 835 } 836 } 837 838 public String toString() { 839 lock.lock(); 840 try { 841 return super.toString(); 842 } finally { 843 lock.unlock(); 844 } 845 } 846 847 851 public void clear() { 852 lock.lock(); 853 try { 854 first = last = null; 855 count = 0; 856 notFull.signalAll(); 857 } finally { 858 lock.unlock(); 859 } 860 } 861 862 873 public Iterator<E> iterator() { 874 return new Itr(); 875 } 876 877 887 public Iterator<E> descendingIterator() { 888 return new DescendingItr(); 889 } 890 891 894 private abstract class AbstractItr implements Iterator<E> { 895 898 Node<E> next; 899 900 906 E nextItem; 907 908 912 private Node<E> lastRet; 913 914 AbstractItr() { 915 advance(); } 917 918 922 abstract void advance(); 923 924 public boolean hasNext() { 925 return next != null; 926 } 927 928 public E next() { 929 if (next == null) 930 throw new NoSuchElementException(); 931 lastRet = next; 932 E x = nextItem; 933 advance(); 934 return x; 935 } 936 937 public void remove() { 938 Node<E> n = lastRet; 939 if (n == null) 940 throw new IllegalStateException (); 941 lastRet = null; 942 removeNode(n); 946 } 947 } 948 949 950 private class Itr extends AbstractItr { 951 void advance() { 952 final ReentrantLock lock = LinkedBlockingDeque.this.lock; 953 lock.lock(); 954 try { 955 next = (next == null)? first : next.next; 956 nextItem = (next == null)? null : next.item; 957 } finally { 958 lock.unlock(); 959 } 960 } 961 } 962 963 966 private class DescendingItr extends AbstractItr { 967 void advance() { 968 final ReentrantLock lock = LinkedBlockingDeque.this.lock; 969 lock.lock(); 970 try { 971 next = (next == null)? last : next.prev; 972 nextItem = (next == null)? null : next.item; 973 } finally { 974 lock.unlock(); 975 } 976 } 977 } 978 979 986 private void writeObject(java.io.ObjectOutputStream s) 987 throws java.io.IOException { 988 lock.lock(); 989 try { 990 s.defaultWriteObject(); 992 for (Node<E> p = first; p != null; p = p.next) 994 s.writeObject(p.item); 995 s.writeObject(null); 997 } finally { 998 lock.unlock(); 999 } 1000 } 1001 1002 1007 private void readObject(java.io.ObjectInputStream s) 1008 throws java.io.IOException , ClassNotFoundException { 1009 s.defaultReadObject(); 1010 count = 0; 1011 first = null; 1012 last = null; 1013 for (;;) { 1015 E item = (E)s.readObject(); 1016 if (item == null) 1017 break; 1018 add(item); 1019 } 1020 } 1021 1022} 1023 | Popular Tags |