提交 4eca6b55 编写于 作者: L lana

Merge

...@@ -35,7 +35,8 @@ ...@@ -35,7 +35,8 @@
package java.util.concurrent; package java.util.concurrent;
import java.util.concurrent.locks.*; import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.*; import java.util.*;
/** /**
...@@ -111,7 +112,7 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E> ...@@ -111,7 +112,7 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
* java.util.PriorityQueue operations within a lock, as was done * java.util.PriorityQueue operations within a lock, as was done
* in a previous version of this class. To maintain * in a previous version of this class. To maintain
* interoperability, a plain PriorityQueue is still used during * interoperability, a plain PriorityQueue is still used during
* serialization, which maintains compatibility at the espense of * serialization, which maintains compatibility at the expense of
* transiently doubling overhead. * transiently doubling overhead.
*/ */
...@@ -308,14 +309,13 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E> ...@@ -308,14 +309,13 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
/** /**
* Mechanics for poll(). Call only while holding lock. * Mechanics for poll(). Call only while holding lock.
*/ */
private E extract() { private E dequeue() {
E result;
int n = size - 1; int n = size - 1;
if (n < 0) if (n < 0)
result = null; return null;
else { else {
Object[] array = queue; Object[] array = queue;
result = (E) array[0]; E result = (E) array[0];
E x = (E) array[n]; E x = (E) array[n];
array[n] = null; array[n] = null;
Comparator<? super E> cmp = comparator; Comparator<? super E> cmp = comparator;
...@@ -324,8 +324,8 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E> ...@@ -324,8 +324,8 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
else else
siftDownUsingComparator(0, x, array, n, cmp); siftDownUsingComparator(0, x, array, n, cmp);
size = n; size = n;
return result;
} }
return result;
} }
/** /**
...@@ -382,39 +382,43 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E> ...@@ -382,39 +382,43 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
*/ */
private static <T> void siftDownComparable(int k, T x, Object[] array, private static <T> void siftDownComparable(int k, T x, Object[] array,
int n) { int n) {
Comparable<? super T> key = (Comparable<? super T>)x; if (n > 0) {
int half = n >>> 1; // loop while a non-leaf Comparable<? super T> key = (Comparable<? super T>)x;
while (k < half) { int half = n >>> 1; // loop while a non-leaf
int child = (k << 1) + 1; // assume left child is least while (k < half) {
Object c = array[child]; int child = (k << 1) + 1; // assume left child is least
int right = child + 1; Object c = array[child];
if (right < n && int right = child + 1;
((Comparable<? super T>) c).compareTo((T) array[right]) > 0) if (right < n &&
c = array[child = right]; ((Comparable<? super T>) c).compareTo((T) array[right]) > 0)
if (key.compareTo((T) c) <= 0) c = array[child = right];
break; if (key.compareTo((T) c) <= 0)
array[k] = c; break;
k = child; array[k] = c;
k = child;
}
array[k] = key;
} }
array[k] = key;
} }
private static <T> void siftDownUsingComparator(int k, T x, Object[] array, private static <T> void siftDownUsingComparator(int k, T x, Object[] array,
int n, int n,
Comparator<? super T> cmp) { Comparator<? super T> cmp) {
int half = n >>> 1; if (n > 0) {
while (k < half) { int half = n >>> 1;
int child = (k << 1) + 1; while (k < half) {
Object c = array[child]; int child = (k << 1) + 1;
int right = child + 1; Object c = array[child];
if (right < n && cmp.compare((T) c, (T) array[right]) > 0) int right = child + 1;
c = array[child = right]; if (right < n && cmp.compare((T) c, (T) array[right]) > 0)
if (cmp.compare(x, (T) c) <= 0) c = array[child = right];
break; if (cmp.compare(x, (T) c) <= 0)
array[k] = c; break;
k = child; array[k] = c;
k = child;
}
array[k] = x;
} }
array[k] = x;
} }
/** /**
...@@ -520,13 +524,11 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E> ...@@ -520,13 +524,11 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
public E poll() { public E poll() {
final ReentrantLock lock = this.lock; final ReentrantLock lock = this.lock;
lock.lock(); lock.lock();
E result;
try { try {
result = extract(); return dequeue();
} finally { } finally {
lock.unlock(); lock.unlock();
} }
return result;
} }
public E take() throws InterruptedException { public E take() throws InterruptedException {
...@@ -534,7 +536,7 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E> ...@@ -534,7 +536,7 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
lock.lockInterruptibly(); lock.lockInterruptibly();
E result; E result;
try { try {
while ( (result = extract()) == null) while ( (result = dequeue()) == null)
notEmpty.await(); notEmpty.await();
} finally { } finally {
lock.unlock(); lock.unlock();
...@@ -548,7 +550,7 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E> ...@@ -548,7 +550,7 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
lock.lockInterruptibly(); lock.lockInterruptibly();
E result; E result;
try { try {
while ( (result = extract()) == null && nanos > 0) while ( (result = dequeue()) == null && nanos > 0)
nanos = notEmpty.awaitNanos(nanos); nanos = notEmpty.awaitNanos(nanos);
} finally { } finally {
lock.unlock(); lock.unlock();
...@@ -559,13 +561,11 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E> ...@@ -559,13 +561,11 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
public E peek() { public E peek() {
final ReentrantLock lock = this.lock; final ReentrantLock lock = this.lock;
lock.lock(); lock.lock();
E result;
try { try {
result = size > 0 ? (E) queue[0] : null; return (size == 0) ? null : (E) queue[0];
} finally { } finally {
lock.unlock(); lock.unlock();
} }
return result;
} }
/** /**
...@@ -649,32 +649,28 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E> ...@@ -649,32 +649,28 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
* @return {@code true} if this queue changed as a result of the call * @return {@code true} if this queue changed as a result of the call
*/ */
public boolean remove(Object o) { public boolean remove(Object o) {
boolean removed = false;
final ReentrantLock lock = this.lock; final ReentrantLock lock = this.lock;
lock.lock(); lock.lock();
try { try {
int i = indexOf(o); int i = indexOf(o);
if (i != -1) { if (i == -1)
removeAt(i); return false;
removed = true; removeAt(i);
} return true;
} finally { } finally {
lock.unlock(); lock.unlock();
} }
return removed;
} }
/** /**
* Identity-based version for use in Itr.remove * Identity-based version for use in Itr.remove
*/ */
private void removeEQ(Object o) { void removeEQ(Object o) {
final ReentrantLock lock = this.lock; final ReentrantLock lock = this.lock;
lock.lock(); lock.lock();
try { try {
Object[] array = queue; Object[] array = queue;
int n = size; for (int i = 0, n = size; i < n; i++) {
for (int i = 0; i < n; i++) {
if (o == array[i]) { if (o == array[i]) {
removeAt(i); removeAt(i);
break; break;
...@@ -694,15 +690,13 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E> ...@@ -694,15 +690,13 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
* @return {@code true} if this queue contains the specified element * @return {@code true} if this queue contains the specified element
*/ */
public boolean contains(Object o) { public boolean contains(Object o) {
int index;
final ReentrantLock lock = this.lock; final ReentrantLock lock = this.lock;
lock.lock(); lock.lock();
try { try {
index = indexOf(o); return indexOf(o) != -1;
} finally { } finally {
lock.unlock(); lock.unlock();
} }
return index != -1;
} }
/** /**
...@@ -728,7 +722,6 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E> ...@@ -728,7 +722,6 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
} }
} }
public String toString() { public String toString() {
final ReentrantLock lock = this.lock; final ReentrantLock lock = this.lock;
lock.lock(); lock.lock();
...@@ -739,7 +732,7 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E> ...@@ -739,7 +732,7 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append('['); sb.append('[');
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
E e = (E)queue[i]; Object e = queue[i];
sb.append(e == this ? "(this Collection)" : e); sb.append(e == this ? "(this Collection)" : e);
if (i != n - 1) if (i != n - 1)
sb.append(',').append(' '); sb.append(',').append(' ');
...@@ -757,23 +750,7 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E> ...@@ -757,23 +750,7 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
* @throws IllegalArgumentException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc}
*/ */
public int drainTo(Collection<? super E> c) { public int drainTo(Collection<? super E> c) {
if (c == null) return drainTo(c, Integer.MAX_VALUE);
throw new NullPointerException();
if (c == this)
throw new IllegalArgumentException();
final ReentrantLock lock = this.lock;
lock.lock();
try {
int n = 0;
E e;
while ( (e = extract()) != null) {
c.add(e);
++n;
}
return n;
} finally {
lock.unlock();
}
} }
/** /**
...@@ -792,11 +769,10 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E> ...@@ -792,11 +769,10 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
final ReentrantLock lock = this.lock; final ReentrantLock lock = this.lock;
lock.lock(); lock.lock();
try { try {
int n = 0; int n = Math.min(size, maxElements);
E e; for (int i = 0; i < n; i++) {
while (n < maxElements && (e = extract()) != null) { c.add((E) queue[0]); // In this order, in case add() throws.
c.add(e); dequeue();
++n;
} }
return n; return n;
} finally { } finally {
...@@ -844,8 +820,7 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E> ...@@ -844,8 +820,7 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
* The following code can be used to dump the queue into a newly * The following code can be used to dump the queue into a newly
* allocated array of {@code String}: * allocated array of {@code String}:
* *
* <pre> * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
* String[] y = x.toArray(new String[0]);</pre>
* *
* Note that {@code toArray(new Object[0])} is identical in function to * Note that {@code toArray(new Object[0])} is identical in function to
* {@code toArray()}. * {@code toArray()}.
...@@ -898,7 +873,7 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E> ...@@ -898,7 +873,7 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
*/ */
final class Itr implements Iterator<E> { final class Itr implements Iterator<E> {
final Object[] array; // Array of all elements final Object[] array; // Array of all elements
int cursor; // index of next element to return; int cursor; // index of next element to return
int lastRet; // index of last element, or -1 if no such int lastRet; // index of last element, or -1 if no such
Itr(Object[] array) { Itr(Object[] array) {
...@@ -926,17 +901,18 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E> ...@@ -926,17 +901,18 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
} }
/** /**
* Saves the state to a stream (that is, serializes it). For * Saves this queue to a stream (that is, serializes it).
* compatibility with previous version of this class, *
* elements are first copied to a java.util.PriorityQueue, * For compatibility with previous version of this class, elements
* which is then serialized. * are first copied to a java.util.PriorityQueue, which is then
* serialized.
*/ */
private void writeObject(java.io.ObjectOutputStream s) private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException { throws java.io.IOException {
lock.lock(); lock.lock();
try { try {
int n = size; // avoid zero capacity argument // avoid zero capacity argument
q = new PriorityQueue<E>(n == 0 ? 1 : n, comparator); q = new PriorityQueue<E>(Math.max(size, 1), comparator);
q.addAll(this); q.addAll(this);
s.defaultWriteObject(); s.defaultWriteObject();
} finally { } finally {
...@@ -946,10 +922,7 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E> ...@@ -946,10 +922,7 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
} }
/** /**
* Reconstitutes the {@code PriorityBlockingQueue} instance from a stream * Reconstitutes this queue from a stream (that is, deserializes it).
* (that is, deserializes it).
*
* @param s the stream
*/ */
private void readObject(java.io.ObjectInputStream s) private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException { throws java.io.IOException, ClassNotFoundException {
......
/* /*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
/* /*
* @test * @test
* @bug 6215625 * @bug 6215625 7161229
* @summary Check correct behavior when last element is removed. * @summary Check correct behavior when last element is removed.
* @author Martin Buchholz * @author Martin Buchholz
*/ */
...@@ -38,9 +38,7 @@ public class LastElement { ...@@ -38,9 +38,7 @@ public class LastElement {
testQueue(new ArrayBlockingQueue<Integer>(10, true)); testQueue(new ArrayBlockingQueue<Integer>(10, true));
testQueue(new ArrayBlockingQueue<Integer>(10, false)); testQueue(new ArrayBlockingQueue<Integer>(10, false));
testQueue(new LinkedTransferQueue<Integer>()); testQueue(new LinkedTransferQueue<Integer>());
testQueue(new PriorityBlockingQueue<Integer>());
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
if (failed > 0) throw new Exception("Some tests failed");
} }
void testQueue(BlockingQueue<Integer> q) throws Throwable { void testQueue(BlockingQueue<Integer> q) throws Throwable {
...@@ -59,6 +57,7 @@ public class LastElement { ...@@ -59,6 +57,7 @@ public class LastElement {
try {check(q.take() == three);} try {check(q.take() == three);}
catch (Throwable t) {unexpected(t);} catch (Throwable t) {unexpected(t);}
check(q.isEmpty() && q.size() == 0); check(q.isEmpty() && q.size() == 0);
check(noRetention(q));
// iterator().remove() // iterator().remove()
q.clear(); q.clear();
...@@ -77,6 +76,26 @@ public class LastElement { ...@@ -77,6 +76,26 @@ public class LastElement {
check(q.isEmpty() && q.size() == 0); check(q.isEmpty() && q.size() == 0);
} }
boolean noRetention(BlockingQueue<?> q) {
if (q instanceof PriorityBlockingQueue) {
PriorityBlockingQueue<?> pbq = (PriorityBlockingQueue) q;
try {
java.lang.reflect.Field queue =
PriorityBlockingQueue.class.getDeclaredField("queue");
queue.setAccessible(true);
Object[] a = (Object[]) queue.get(pbq);
return a[0] == null;
}
catch (NoSuchFieldException e) {
unexpected(e);
}
catch (IllegalAccessException e) {
// ignore - security manager must be installed
}
}
return true;
}
//--------------------- Infrastructure --------------------------- //--------------------- Infrastructure ---------------------------
volatile int passed = 0, failed = 0; volatile int passed = 0, failed = 0;
void pass() {passed++;} void pass() {passed++;}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册