This commit is contained in:
Phil Race 2017-07-25 14:07:37 -07:00
commit 384694c8fe
81 changed files with 2086 additions and 1772 deletions

View File

@ -436,3 +436,4 @@ e6c4f6ef717d104dba880e2dae538690c993b46f jdk-9+175
9f27d513658d5375b0e26846857d92563f279073 jdk-9+176 9f27d513658d5375b0e26846857d92563f279073 jdk-9+176
80acf577b7d0b886fb555c9916552844f6cc72af jdk-9+177 80acf577b7d0b886fb555c9916552844f6cc72af jdk-9+177
e069834e2c518a7bc2ffadc8c7e3cd7ec69fa8a0 jdk-10+15 e069834e2c518a7bc2ffadc8c7e3cd7ec69fa8a0 jdk-10+15
3281b964ab104002623d744e8b77a12269b70acd jdk-10+16

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2017, 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
@ -1378,7 +1378,7 @@ JDWP "Java(tm) Debug Wire Protocol"
(Repeat lines "The number of entries in the line table for this method." (Repeat lines "The number of entries in the line table for this method."
(Group LineInfo (Group LineInfo
(long lineCodeIndex "Initial code index of the line, " (long lineCodeIndex "Initial code index of the line, "
"start <= lineCodeIndex < end") "start &lt;= lineCodeIndex &lt; end")
(int lineNumber "Line number.") (int lineNumber "Line number.")
) )
) )
@ -1409,13 +1409,13 @@ JDWP "Java(tm) Debug Wire Protocol"
"First code index at which the variable is visible (unsigned). " "First code index at which the variable is visible (unsigned). "
"Used in conjunction with <code>length</code>. " "Used in conjunction with <code>length</code>. "
"The variable can be get or set only when the current " "The variable can be get or set only when the current "
"<code>codeIndex</code> <= current frame code index < <code>codeIndex + length</code> ") "<code>codeIndex</code> &lt;= current frame code index &lt; <code>codeIndex + length</code> ")
(string name "The variable's name.") (string name "The variable's name.")
(string signature "The variable type's JNI signature.") (string signature "The variable type's JNI signature.")
(int length (int length
"Unsigned value used in conjunction with <code>codeIndex</code>. " "Unsigned value used in conjunction with <code>codeIndex</code>. "
"The variable can be get or set only when the current " "The variable can be get or set only when the current "
"<code>codeIndex</code> <= current frame code index < <code>code index + length</code> ") "<code>codeIndex</code> &lt;= current frame code index &lt; <code>code index + length</code> ")
(int slot "The local variable's index in its frame") (int slot "The local variable's index in its frame")
) )
) )
@ -1502,7 +1502,7 @@ JDWP "Java(tm) Debug Wire Protocol"
"First code index at which the variable is visible (unsigned). " "First code index at which the variable is visible (unsigned). "
"Used in conjunction with <code>length</code>. " "Used in conjunction with <code>length</code>. "
"The variable can be get or set only when the current " "The variable can be get or set only when the current "
"<code>codeIndex</code> <= current frame code index < <code>codeIndex + length</code> ") "<code>codeIndex</code> &lt;= current frame code index &lt; <code>codeIndex + length</code> ")
(string name "The variable's name.") (string name "The variable's name.")
(string signature "The variable type's JNI signature.") (string signature "The variable type's JNI signature.")
(string genericSignature "The variable type's generic " (string genericSignature "The variable type's generic "
@ -1510,7 +1510,7 @@ JDWP "Java(tm) Debug Wire Protocol"
(int length (int length
"Unsigned value used in conjunction with <code>codeIndex</code>. " "Unsigned value used in conjunction with <code>codeIndex</code>. "
"The variable can be get or set only when the current " "The variable can be get or set only when the current "
"<code>codeIndex</code> <= current frame code index < <code>code index + length</code> ") "<code>codeIndex</code> &lt;= current frame code index &lt; <code>code index + length</code> ")
(int slot "The local variable's index in its frame") (int slot "The local variable's index in its frame")
) )
) )

View File

@ -243,7 +243,7 @@ public class ArrayDeque<E> extends AbstractCollection<E>
* Index i must be logically ahead of index j. * Index i must be logically ahead of index j.
* Precondition: 0 <= i < modulus, 0 <= j < modulus. * Precondition: 0 <= i < modulus, 0 <= j < modulus.
* @return the "circular distance" from j to i; corner case i == j * @return the "circular distance" from j to i; corner case i == j
* is diambiguated to "empty", returning 0. * is disambiguated to "empty", returning 0.
*/ */
static final int sub(int i, int j, int modulus) { static final int sub(int i, int j, int modulus) {
if ((i -= j) < 0) i += modulus; if ((i -= j) < 0) i += modulus;
@ -310,8 +310,7 @@ public class ArrayDeque<E> extends AbstractCollection<E>
/** /**
* Adds all of the elements in the specified collection at the end * Adds all of the elements in the specified collection at the end
* of this deque, as if by calling {@link #addLast} on each one, * of this deque, as if by calling {@link #addLast} on each one,
* in the order that they are returned by the collection's * in the order that they are returned by the collection's iterator.
* iterator.
* *
* @param c the elements to be inserted into this deque * @param c the elements to be inserted into this deque
* @return {@code true} if this deque changed as a result of the call * @return {@code true} if this deque changed as a result of the call
@ -508,8 +507,8 @@ public class ArrayDeque<E> extends AbstractCollection<E>
/** /**
* Retrieves and removes the head of the queue represented by this deque. * Retrieves and removes the head of the queue represented by this deque.
* *
* This method differs from {@link #poll poll} only in that it throws an * This method differs from {@link #poll() poll()} only in that it
* exception if this deque is empty. * throws an exception if this deque is empty.
* *
* <p>This method is equivalent to {@link #removeFirst}. * <p>This method is equivalent to {@link #removeFirst}.
* *

View File

@ -514,15 +514,10 @@ public class ArrayList<E> extends AbstractList<E>
*/ */
public E remove(int index) { public E remove(int index) {
Objects.checkIndex(index, size); Objects.checkIndex(index, size);
final Object[] es = elementData;
modCount++; @SuppressWarnings("unchecked") E oldValue = (E) es[index];
E oldValue = elementData(index); fastRemove(es, index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue; return oldValue;
} }
@ -541,33 +536,35 @@ public class ArrayList<E> extends AbstractList<E>
* @return {@code true} if this list contained the specified element * @return {@code true} if this list contained the specified element
*/ */
public boolean remove(Object o) { public boolean remove(Object o) {
final Object[] es = elementData;
final int size = this.size;
int i = 0;
found: {
if (o == null) { if (o == null) {
for (int index = 0; index < size; index++) for (; i < size; i++)
if (elementData[index] == null) { if (es[i] == null)
fastRemove(index); break found;
return true;
}
} else { } else {
for (int index = 0; index < size; index++) for (; i < size; i++)
if (o.equals(elementData[index])) { if (o.equals(es[i]))
fastRemove(index); break found;
return true;
}
} }
return false; return false;
} }
fastRemove(es, i);
return true;
}
/** /**
* Private remove method that skips bounds checking and does not * Private remove method that skips bounds checking and does not
* return the value removed. * return the value removed.
*/ */
private void fastRemove(int index) { private void fastRemove(Object[] es, int i) {
modCount++; modCount++;
int numMoved = size - index - 1; final int newSize;
if (numMoved > 0) if ((newSize = size - 1) > i)
System.arraycopy(elementData, index+1, elementData, index, System.arraycopy(es, i + 1, es, i, newSize - i);
numMoved); es[size = newSize] = null;
elementData[--size] = null; // clear to let GC do its work
} }
/** /**
@ -743,12 +740,14 @@ public class ArrayList<E> extends AbstractList<E>
final int from, final int end) { final int from, final int end) {
Objects.requireNonNull(c); Objects.requireNonNull(c);
final Object[] es = elementData; final Object[] es = elementData;
final boolean modified;
int r; int r;
// Optimize for initial run of survivors // Optimize for initial run of survivors
for (r = from; r < end && c.contains(es[r]) == complement; r++) for (r = from;; r++) {
; if (r == end)
if (modified = (r < end)) { return false;
if (c.contains(es[r]) != complement)
break;
}
int w = r++; int w = r++;
try { try {
for (Object e; r < end; r++) for (Object e; r < end; r++)
@ -764,8 +763,7 @@ public class ArrayList<E> extends AbstractList<E>
modCount += end - w; modCount += end - w;
shiftTailOverGap(es, w, end); shiftTailOverGap(es, w, end);
} }
} return true;
return modified;
} }
/** /**
@ -784,7 +782,7 @@ public class ArrayList<E> extends AbstractList<E>
int expectedModCount = modCount; int expectedModCount = modCount;
s.defaultWriteObject(); s.defaultWriteObject();
// Write out size as capacity for behavioural compatibility with clone() // Write out size as capacity for behavioral compatibility with clone()
s.writeInt(size); s.writeInt(size);
// Write out all elements in the proper order. // Write out all elements in the proper order.

View File

@ -37,15 +37,14 @@ package java.util;
/** /**
* A collection designed for holding elements prior to processing. * A collection designed for holding elements prior to processing.
* Besides basic {@link java.util.Collection Collection} operations, * Besides basic {@link Collection} operations, queues provide
* queues provide additional insertion, extraction, and inspection * additional insertion, extraction, and inspection operations.
* operations. Each of these methods exists in two forms: one throws * Each of these methods exists in two forms: one throws an exception
* an exception if the operation fails, the other returns a special * if the operation fails, the other returns a special value (either
* value (either {@code null} or {@code false}, depending on the * {@code null} or {@code false}, depending on the operation). The
* operation). The latter form of the insert operation is designed * latter form of the insert operation is designed specifically for
* specifically for use with capacity-restricted {@code Queue} * use with capacity-restricted {@code Queue} implementations; in most
* implementations; in most implementations, insert operations cannot * implementations, insert operations cannot fail.
* fail.
* *
* <table class="plain"> * <table class="plain">
* <caption>Summary of Queue methods</caption> * <caption>Summary of Queue methods</caption>
@ -56,18 +55,18 @@ package java.util;
* </tr> * </tr>
* <tr> * <tr>
* <td><b>Insert</b></td> * <td><b>Insert</b></td>
* <td>{@link Queue#add add(e)}</td> * <td>{@link #add(Object) add(e)}</td>
* <td>{@link Queue#offer offer(e)}</td> * <td>{@link #offer(Object) offer(e)}</td>
* </tr> * </tr>
* <tr> * <tr>
* <td><b>Remove</b></td> * <td><b>Remove</b></td>
* <td>{@link Queue#remove remove()}</td> * <td>{@link #remove() remove()}</td>
* <td>{@link Queue#poll poll()}</td> * <td>{@link #poll() poll()}</td>
* </tr> * </tr>
* <tr> * <tr>
* <td><b>Examine</b></td> * <td><b>Examine</b></td>
* <td>{@link Queue#element element()}</td> * <td>{@link #element() element()}</td>
* <td>{@link Queue#peek peek()}</td> * <td>{@link #peek() peek()}</td>
* </tr> * </tr>
* </table> * </table>
* *
@ -173,8 +172,8 @@ public interface Queue<E> extends Collection<E> {
/** /**
* Retrieves and removes the head of this queue. This method differs * Retrieves and removes the head of this queue. This method differs
* from {@link #poll poll} only in that it throws an exception if this * from {@link #poll() poll()} only in that it throws an exception if
* queue is empty. * this queue is empty.
* *
* @return the head of this queue * @return the head of this queue
* @throws NoSuchElementException if this queue is empty * @throws NoSuchElementException if this queue is empty

View File

@ -67,22 +67,22 @@ import java.util.NoSuchElementException;
* </tr> * </tr>
* <tr> * <tr>
* <td><b>Insert</b></td> * <td><b>Insert</b></td>
* <td>{@link #addFirst addFirst(e)}</td> * <td>{@link #addFirst(Object) addFirst(e)}</td>
* <td>{@link #offerFirst(Object) offerFirst(e)}</td> * <td>{@link #offerFirst(Object) offerFirst(e)}</td>
* <td>{@link #putFirst putFirst(e)}</td> * <td>{@link #putFirst(Object) putFirst(e)}</td>
* <td>{@link #offerFirst(Object, long, TimeUnit) offerFirst(e, time, unit)}</td> * <td>{@link #offerFirst(Object, long, TimeUnit) offerFirst(e, time, unit)}</td>
* </tr> * </tr>
* <tr> * <tr>
* <td><b>Remove</b></td> * <td><b>Remove</b></td>
* <td>{@link #removeFirst removeFirst()}</td> * <td>{@link #removeFirst() removeFirst()}</td>
* <td>{@link #pollFirst pollFirst()}</td> * <td>{@link #pollFirst() pollFirst()}</td>
* <td>{@link #takeFirst takeFirst()}</td> * <td>{@link #takeFirst() takeFirst()}</td>
* <td>{@link #pollFirst(long, TimeUnit) pollFirst(time, unit)}</td> * <td>{@link #pollFirst(long, TimeUnit) pollFirst(time, unit)}</td>
* </tr> * </tr>
* <tr> * <tr>
* <td><b>Examine</b></td> * <td><b>Examine</b></td>
* <td>{@link #getFirst getFirst()}</td> * <td>{@link #getFirst() getFirst()}</td>
* <td>{@link #peekFirst peekFirst()}</td> * <td>{@link #peekFirst() peekFirst()}</td>
* <td><em>not applicable</em></td> * <td><em>not applicable</em></td>
* <td><em>not applicable</em></td> * <td><em>not applicable</em></td>
* </tr> * </tr>
@ -98,22 +98,22 @@ import java.util.NoSuchElementException;
* </tr> * </tr>
* <tr> * <tr>
* <td><b>Insert</b></td> * <td><b>Insert</b></td>
* <td>{@link #addLast addLast(e)}</td> * <td>{@link #addLast(Object) addLast(e)}</td>
* <td>{@link #offerLast(Object) offerLast(e)}</td> * <td>{@link #offerLast(Object) offerLast(e)}</td>
* <td>{@link #putLast putLast(e)}</td> * <td>{@link #putLast(Object) putLast(e)}</td>
* <td>{@link #offerLast(Object, long, TimeUnit) offerLast(e, time, unit)}</td> * <td>{@link #offerLast(Object, long, TimeUnit) offerLast(e, time, unit)}</td>
* </tr> * </tr>
* <tr> * <tr>
* <td><b>Remove</b></td> * <td><b>Remove</b></td>
* <td>{@link #removeLast() removeLast()}</td> * <td>{@link #removeLast() removeLast()}</td>
* <td>{@link #pollLast() pollLast()}</td> * <td>{@link #pollLast() pollLast()}</td>
* <td>{@link #takeLast takeLast()}</td> * <td>{@link #takeLast() takeLast()}</td>
* <td>{@link #pollLast(long, TimeUnit) pollLast(time, unit)}</td> * <td>{@link #pollLast(long, TimeUnit) pollLast(time, unit)}</td>
* </tr> * </tr>
* <tr> * <tr>
* <td><b>Examine</b></td> * <td><b>Examine</b></td>
* <td>{@link #getLast getLast()}</td> * <td>{@link #getLast() getLast()}</td>
* <td>{@link #peekLast peekLast()}</td> * <td>{@link #peekLast() peekLast()}</td>
* <td><em>not applicable</em></td> * <td><em>not applicable</em></td>
* <td><em>not applicable</em></td> * <td><em>not applicable</em></td>
* </tr> * </tr>
@ -512,7 +512,7 @@ public interface BlockingDeque<E> extends BlockingQueue<E>, Deque<E> {
/** /**
* Retrieves and removes the head of the queue represented by this deque * Retrieves and removes the head of the queue represented by this deque
* (in other words, the first element of this deque). * (in other words, the first element of this deque).
* This method differs from {@link #poll poll} only in that it * This method differs from {@link #poll() poll()} only in that it
* throws an exception if this deque is empty. * throws an exception if this deque is empty.
* *
* <p>This method is equivalent to {@link #removeFirst() removeFirst}. * <p>This method is equivalent to {@link #removeFirst() removeFirst}.
@ -563,7 +563,7 @@ public interface BlockingDeque<E> extends BlockingQueue<E>, Deque<E> {
/** /**
* Retrieves, but does not remove, the head of the queue represented by * Retrieves, but does not remove, the head of the queue represented by
* this deque (in other words, the first element of this deque). * this deque (in other words, the first element of this deque).
* This method differs from {@link #peek peek} only in that it throws an * This method differs from {@link #peek() peek} only in that it throws an
* exception if this deque is empty. * exception if this deque is empty.
* *
* <p>This method is equivalent to {@link #getFirst() getFirst}. * <p>This method is equivalent to {@link #getFirst() getFirst}.

View File

@ -39,10 +39,9 @@ import java.util.Collection;
import java.util.Queue; import java.util.Queue;
/** /**
* A {@link java.util.Queue} that additionally supports operations * A {@link Queue} that additionally supports operations that wait for
* that wait for the queue to become non-empty when retrieving an * the queue to become non-empty when retrieving an element, and wait
* element, and wait for space to become available in the queue when * for space to become available in the queue when storing an element.
* storing an element.
* *
* <p>{@code BlockingQueue} methods come in four forms, with different ways * <p>{@code BlockingQueue} methods come in four forms, with different ways
* of handling operations that cannot be satisfied immediately, but may be * of handling operations that cannot be satisfied immediately, but may be
@ -64,22 +63,22 @@ import java.util.Queue;
* </tr> * </tr>
* <tr> * <tr>
* <td><b>Insert</b></td> * <td><b>Insert</b></td>
* <td>{@link #add add(e)}</td> * <td>{@link #add(Object) add(e)}</td>
* <td>{@link #offer offer(e)}</td> * <td>{@link #offer(Object) offer(e)}</td>
* <td>{@link #put put(e)}</td> * <td>{@link #put(Object) put(e)}</td>
* <td>{@link #offer(Object, long, TimeUnit) offer(e, time, unit)}</td> * <td>{@link #offer(Object, long, TimeUnit) offer(e, time, unit)}</td>
* </tr> * </tr>
* <tr> * <tr>
* <td><b>Remove</b></td> * <td><b>Remove</b></td>
* <td>{@link #remove remove()}</td> * <td>{@link #remove() remove()}</td>
* <td>{@link #poll poll()}</td> * <td>{@link #poll() poll()}</td>
* <td>{@link #take take()}</td> * <td>{@link #take() take()}</td>
* <td>{@link #poll(long, TimeUnit) poll(time, unit)}</td> * <td>{@link #poll(long, TimeUnit) poll(time, unit)}</td>
* </tr> * </tr>
* <tr> * <tr>
* <td><b>Examine</b></td> * <td><b>Examine</b></td>
* <td>{@link #element element()}</td> * <td>{@link #element() element()}</td>
* <td>{@link #peek peek()}</td> * <td>{@link #peek() peek()}</td>
* <td><em>not applicable</em></td> * <td><em>not applicable</em></td>
* <td><em>not applicable</em></td> * <td><em>not applicable</em></td>
* </tr> * </tr>
@ -99,7 +98,7 @@ import java.util.Queue;
* *
* <p>{@code BlockingQueue} implementations are designed to be used * <p>{@code BlockingQueue} implementations are designed to be used
* primarily for producer-consumer queues, but additionally support * primarily for producer-consumer queues, but additionally support
* the {@link java.util.Collection} interface. So, for example, it is * the {@link Collection} interface. So, for example, it is
* possible to remove an arbitrary element from a queue using * possible to remove an arbitrary element from a queue using
* {@code remove(x)}. However, such operations are in general * {@code remove(x)}. However, such operations are in general
* <em>not</em> performed very efficiently, and are intended for only * <em>not</em> performed very efficiently, and are intended for only

View File

@ -159,8 +159,7 @@ import jdk.internal.misc.Unsafe;
* ordering, or on any other objects or values that may transiently * ordering, or on any other objects or values that may transiently
* change while computation is in progress; and except for forEach * change while computation is in progress; and except for forEach
* actions, should ideally be side-effect-free. Bulk operations on * actions, should ideally be side-effect-free. Bulk operations on
* {@link java.util.Map.Entry} objects do not support method {@code * {@link Map.Entry} objects do not support method {@code setValue}.
* setValue}.
* *
* <ul> * <ul>
* <li>forEach: Performs a given action on each element. * <li>forEach: Performs a given action on each element.

View File

@ -42,8 +42,7 @@ import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
/** /**
* A {@link java.util.Map} providing thread safety and atomicity * A {@link Map} providing thread safety and atomicity guarantees.
* guarantees.
* *
* <p>To maintain the specified guarantees, default implementations of * <p>To maintain the specified guarantees, default implementations of
* methods including {@link #putIfAbsent} inherited from {@link Map} * methods including {@link #putIfAbsent} inherited from {@link Map}

View File

@ -1821,9 +1821,11 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
* The set's spliterator additionally reports {@link Spliterator#CONCURRENT}, * The set's spliterator additionally reports {@link Spliterator#CONCURRENT},
* {@link Spliterator#NONNULL}, {@link Spliterator#SORTED} and * {@link Spliterator#NONNULL}, {@link Spliterator#SORTED} and
* {@link Spliterator#ORDERED}, with an encounter order that is ascending * {@link Spliterator#ORDERED}, with an encounter order that is ascending
* key order. The spliterator's comparator (see * key order.
* {@link java.util.Spliterator#getComparator()}) is {@code null} if *
* the map's comparator (see {@link #comparator()}) is {@code null}. * <p>The {@linkplain Spliterator#getComparator() spliterator's comparator}
* is {@code null} if the {@linkplain #comparator() map's comparator}
* is {@code null}.
* Otherwise, the spliterator's comparator is the same as or imposes the * Otherwise, the spliterator's comparator is the same as or imposes the
* same total ordering as the map's comparator. * same total ordering as the map's comparator.
* *

View File

@ -491,9 +491,9 @@ public class ConcurrentSkipListSet<E>
* encounter order that is ascending order. Overriding implementations * encounter order that is ascending order. Overriding implementations
* should document the reporting of additional characteristic values. * should document the reporting of additional characteristic values.
* *
* <p>The spliterator's comparator (see * <p>The {@linkplain Spliterator#getComparator() spliterator's comparator}
* {@link java.util.Spliterator#getComparator()}) is {@code null} if * is {@code null} if the {@linkplain #comparator() set's comparator}
* the set's comparator (see {@link #comparator()}) is {@code null}. * is {@code null}.
* Otherwise, the spliterator's comparator is the same as or imposes the * Otherwise, the spliterator's comparator is the same as or imposes the
* same total ordering as the set's comparator. * same total ordering as the set's comparator.
* *

View File

@ -46,7 +46,7 @@ import java.util.function.Consumer;
import java.util.function.Predicate; import java.util.function.Predicate;
/** /**
* A {@link java.util.Set} that uses an internal {@link CopyOnWriteArrayList} * A {@link Set} that uses an internal {@link CopyOnWriteArrayList}
* for all of its operations. Thus, it shares the same basic properties: * for all of its operations. Thus, it shares the same basic properties:
* <ul> * <ul>
* <li>It is best suited for applications in which set sizes generally * <li>It is best suited for applications in which set sizes generally

View File

@ -57,8 +57,7 @@ import java.lang.invoke.VarHandle;
* decremented; otherwise, the completion action is performed, and if * decremented; otherwise, the completion action is performed, and if
* this completer itself has a completer, the process is continued * this completer itself has a completer, the process is continued
* with its completer. As is the case with related synchronization * with its completer. As is the case with related synchronization
* components such as {@link java.util.concurrent.Phaser Phaser} and * components such as {@link Phaser} and {@link Semaphore}, these methods
* {@link java.util.concurrent.Semaphore Semaphore}, these methods
* affect only internal counts; they do not establish any further * affect only internal counts; they do not establish any further
* internal bookkeeping. In particular, the identities of pending * internal bookkeeping. In particular, the identities of pending
* tasks are not maintained. As illustrated below, you can create * tasks are not maintained. As illustrated below, you can create

View File

@ -322,17 +322,6 @@ public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
} }
} }
/**
* Returns first element only if it is expired.
* Used only by drainTo. Call only when holding lock.
*/
private E peekExpired() {
// assert lock.isHeldByCurrentThread();
E first = q.peek();
return (first == null || first.getDelay(NANOSECONDS) > 0) ?
null : first;
}
/** /**
* @throws UnsupportedOperationException {@inheritDoc} * @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc} * @throws ClassCastException {@inheritDoc}
@ -340,22 +329,7 @@ public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
* @throws IllegalArgumentException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc}
*/ */
public int drainTo(Collection<? super E> c) { public int drainTo(Collection<? super E> c) {
Objects.requireNonNull(c); return drainTo(c, Integer.MAX_VALUE);
if (c == this)
throw new IllegalArgumentException();
final ReentrantLock lock = this.lock;
lock.lock();
try {
int n = 0;
for (E e; (e = peekExpired()) != null;) {
c.add(e); // In this order, in case add() throws.
q.poll();
++n;
}
return n;
} finally {
lock.unlock();
}
} }
/** /**
@ -374,8 +348,11 @@ public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
lock.lock(); lock.lock();
try { try {
int n = 0; int n = 0;
for (E e; n < maxElements && (e = peekExpired()) != null;) { for (E first;
c.add(e); // In this order, in case add() throws. n < maxElements
&& (first = q.peek()) != null
&& first.getDelay(NANOSECONDS) <= 0;) {
c.add(first); // In this order, in case add() throws.
q.poll(); q.poll();
++n; ++n;
} }

View File

@ -134,11 +134,11 @@ import java.util.concurrent.locks.ReentrantLock;
* {@link #isCompletedNormally} is true if a task completed without * {@link #isCompletedNormally} is true if a task completed without
* cancellation or encountering an exception; {@link #isCancelled} is * cancellation or encountering an exception; {@link #isCancelled} is
* true if the task was cancelled (in which case {@link #getException} * true if the task was cancelled (in which case {@link #getException}
* returns a {@link java.util.concurrent.CancellationException}); and * returns a {@link CancellationException}); and
* {@link #isCompletedAbnormally} is true if a task was either * {@link #isCompletedAbnormally} is true if a task was either
* cancelled or encountered an exception, in which case {@link * cancelled or encountered an exception, in which case {@link
* #getException} will return either the encountered exception or * #getException} will return either the encountered exception or
* {@link java.util.concurrent.CancellationException}. * {@link CancellationException}.
* *
* <p>The ForkJoinTask class is not usually directly subclassed. * <p>The ForkJoinTask class is not usually directly subclassed.
* Instead, you subclass one of the abstract classes that support a * Instead, you subclass one of the abstract classes that support a
@ -695,13 +695,13 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
} }
/** /**
* Returns the result of the computation when it {@link #isDone is * Returns the result of the computation when it
* done}. This method differs from {@link #get()} in that * {@linkplain #isDone is done}.
* abnormal completion results in {@code RuntimeException} or * This method differs from {@link #get()} in that abnormal
* {@code Error}, not {@code ExecutionException}, and that * completion results in {@code RuntimeException} or {@code Error},
* interrupts of the calling thread do <em>not</em> cause the * not {@code ExecutionException}, and that interrupts of the
* method to abruptly return by throwing {@code * calling thread do <em>not</em> cause the method to abruptly
* InterruptedException}. * return by throwing {@code InterruptedException}.
* *
* @return the computed result * @return the computed result
*/ */

View File

@ -651,7 +651,7 @@ public class LinkedBlockingDeque<E>
/** /**
* Retrieves and removes the head of the queue represented by this deque. * Retrieves and removes the head of the queue represented by this deque.
* This method differs from {@link #poll poll} only in that it throws an * This method differs from {@link #poll() poll()} only in that it throws an
* exception if this deque is empty. * exception if this deque is empty.
* *
* <p>This method is equivalent to {@link #removeFirst() removeFirst}. * <p>This method is equivalent to {@link #removeFirst() removeFirst}.
@ -677,7 +677,7 @@ public class LinkedBlockingDeque<E>
/** /**
* Retrieves, but does not remove, the head of the queue represented by * Retrieves, but does not remove, the head of the queue represented by
* this deque. This method differs from {@link #peek peek} only in that * this deque. This method differs from {@link #peek() peek()} only in that
* it throws an exception if this deque is empty. * it throws an exception if this deque is empty.
* *
* <p>This method is equivalent to {@link #getFirst() getFirst}. * <p>This method is equivalent to {@link #getFirst() getFirst}.

View File

@ -1275,8 +1275,7 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
* return {@code false}. * return {@code false}.
* *
* @return {@code true} (as specified by * @return {@code true} (as specified by
* {@link java.util.concurrent.BlockingQueue#offer(Object,long,TimeUnit) * {@link BlockingQueue#offer(Object,long,TimeUnit) BlockingQueue.offer})
* BlockingQueue.offer})
* @throws NullPointerException if the specified element is null * @throws NullPointerException if the specified element is null
*/ */
public boolean offer(E e, long timeout, TimeUnit unit) { public boolean offer(E e, long timeout, TimeUnit unit) {
@ -1567,8 +1566,7 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
* {@code LinkedTransferQueue} is not capacity constrained. * {@code LinkedTransferQueue} is not capacity constrained.
* *
* @return {@code Integer.MAX_VALUE} (as specified by * @return {@code Integer.MAX_VALUE} (as specified by
* {@link java.util.concurrent.BlockingQueue#remainingCapacity() * {@link BlockingQueue#remainingCapacity()})
* BlockingQueue.remainingCapacity})
*/ */
public int remainingCapacity() { public int remainingCapacity() {
return Integer.MAX_VALUE; return Integer.MAX_VALUE;

View File

@ -42,9 +42,8 @@ import java.util.concurrent.locks.LockSupport;
/** /**
* A reusable synchronization barrier, similar in functionality to * A reusable synchronization barrier, similar in functionality to
* {@link java.util.concurrent.CyclicBarrier CyclicBarrier} and * {@link CyclicBarrier} and {@link CountDownLatch} but supporting
* {@link java.util.concurrent.CountDownLatch CountDownLatch} * more flexible usage.
* but supporting more flexible usage.
* *
* <p><b>Registration.</b> Unlike the case for other barriers, the * <p><b>Registration.</b> Unlike the case for other barriers, the
* number of parties <em>registered</em> to synchronize on a phaser * number of parties <em>registered</em> to synchronize on a phaser

View File

@ -80,7 +80,7 @@ package java.util.concurrent;
* Runnable beeper = () -> System.out.println("beep"); * Runnable beeper = () -> System.out.println("beep");
* ScheduledFuture<?> beeperHandle = * ScheduledFuture<?> beeperHandle =
* scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS); * scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
* Runnable canceller = () -> beeperHandle.cancel(true); * Runnable canceller = () -> beeperHandle.cancel(false);
* scheduler.schedule(canceller, 1, HOURS); * scheduler.schedule(canceller, 1, HOURS);
* } * }
* }}</pre> * }}</pre>
@ -91,8 +91,7 @@ package java.util.concurrent;
public interface ScheduledExecutorService extends ExecutorService { public interface ScheduledExecutorService extends ExecutorService {
/** /**
* Creates and executes a one-shot action that becomes enabled * Submits a one-shot task that becomes enabled after the given delay.
* after the given delay.
* *
* @param command the task to execute * @param command the task to execute
* @param delay the time from now to delay execution * @param delay the time from now to delay execution
@ -102,14 +101,14 @@ public interface ScheduledExecutorService extends ExecutorService {
* {@code null} upon completion * {@code null} upon completion
* @throws RejectedExecutionException if the task cannot be * @throws RejectedExecutionException if the task cannot be
* scheduled for execution * scheduled for execution
* @throws NullPointerException if command is null * @throws NullPointerException if command or unit is null
*/ */
public ScheduledFuture<?> schedule(Runnable command, public ScheduledFuture<?> schedule(Runnable command,
long delay, TimeUnit unit); long delay, TimeUnit unit);
/** /**
* Creates and executes a ScheduledFuture that becomes enabled after the * Submits a value-returning one-shot task that becomes enabled
* given delay. * after the given delay.
* *
* @param callable the function to execute * @param callable the function to execute
* @param delay the time from now to delay execution * @param delay the time from now to delay execution
@ -118,15 +117,15 @@ public interface ScheduledExecutorService extends ExecutorService {
* @return a ScheduledFuture that can be used to extract result or cancel * @return a ScheduledFuture that can be used to extract result or cancel
* @throws RejectedExecutionException if the task cannot be * @throws RejectedExecutionException if the task cannot be
* scheduled for execution * scheduled for execution
* @throws NullPointerException if callable is null * @throws NullPointerException if callable or unit is null
*/ */
public <V> ScheduledFuture<V> schedule(Callable<V> callable, public <V> ScheduledFuture<V> schedule(Callable<V> callable,
long delay, TimeUnit unit); long delay, TimeUnit unit);
/** /**
* Creates and executes a periodic action that becomes enabled first * Submits a periodic action that becomes enabled first after the
* after the given initial delay, and subsequently with the given * given initial delay, and subsequently with the given period;
* period; that is, executions will commence after * that is, executions will commence after
* {@code initialDelay}, then {@code initialDelay + period}, then * {@code initialDelay}, then {@code initialDelay + period}, then
* {@code initialDelay + 2 * period}, and so on. * {@code initialDelay + 2 * period}, and so on.
* *
@ -137,8 +136,8 @@ public interface ScheduledExecutorService extends ExecutorService {
* via the returned future. * via the returned future.
* <li>The executor terminates, also resulting in task cancellation. * <li>The executor terminates, also resulting in task cancellation.
* <li>An execution of the task throws an exception. In this case * <li>An execution of the task throws an exception. In this case
* calling {@link Future#get() get} on the returned future will * calling {@link Future#get() get} on the returned future will throw
* throw {@link ExecutionException}. * {@link ExecutionException}, holding the exception as its cause.
* </ul> * </ul>
* Subsequent executions are suppressed. Subsequent calls to * Subsequent executions are suppressed. Subsequent calls to
* {@link Future#isDone isDone()} on the returned future will * {@link Future#isDone isDone()} on the returned future will
@ -159,7 +158,7 @@ public interface ScheduledExecutorService extends ExecutorService {
* abnormal termination of a task execution. * abnormal termination of a task execution.
* @throws RejectedExecutionException if the task cannot be * @throws RejectedExecutionException if the task cannot be
* scheduled for execution * scheduled for execution
* @throws NullPointerException if command is null * @throws NullPointerException if command or unit is null
* @throws IllegalArgumentException if period less than or equal to zero * @throws IllegalArgumentException if period less than or equal to zero
*/ */
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
@ -168,10 +167,10 @@ public interface ScheduledExecutorService extends ExecutorService {
TimeUnit unit); TimeUnit unit);
/** /**
* Creates and executes a periodic action that becomes enabled first * Submits a periodic action that becomes enabled first after the
* after the given initial delay, and subsequently with the * given initial delay, and subsequently with the given delay
* given delay between the termination of one execution and the * between the termination of one execution and the commencement of
* commencement of the next. * the next.
* *
* <p>The sequence of task executions continues indefinitely until * <p>The sequence of task executions continues indefinitely until
* one of the following exceptional completions occur: * one of the following exceptional completions occur:
@ -180,8 +179,8 @@ public interface ScheduledExecutorService extends ExecutorService {
* via the returned future. * via the returned future.
* <li>The executor terminates, also resulting in task cancellation. * <li>The executor terminates, also resulting in task cancellation.
* <li>An execution of the task throws an exception. In this case * <li>An execution of the task throws an exception. In this case
* calling {@link Future#get() get} on the returned future will * calling {@link Future#get() get} on the returned future will throw
* throw {@link ExecutionException}. * {@link ExecutionException}, holding the exception as its cause.
* </ul> * </ul>
* Subsequent executions are suppressed. Subsequent calls to * Subsequent executions are suppressed. Subsequent calls to
* {@link Future#isDone isDone()} on the returned future will * {@link Future#isDone isDone()} on the returned future will
@ -199,7 +198,7 @@ public interface ScheduledExecutorService extends ExecutorService {
* abnormal termination of a task execution. * abnormal termination of a task execution.
* @throws RejectedExecutionException if the task cannot be * @throws RejectedExecutionException if the task cannot be
* scheduled for execution * scheduled for execution
* @throws NullPointerException if command is null * @throws NullPointerException if command or unit is null
* @throws IllegalArgumentException if delay less than or equal to zero * @throws IllegalArgumentException if delay less than or equal to zero
*/ */
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,

View File

@ -44,6 +44,7 @@ import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
@ -87,6 +88,11 @@ import java.util.concurrent.locks.ReentrantLock;
* use {@code allowCoreThreadTimeOut} because this may leave the pool * use {@code allowCoreThreadTimeOut} because this may leave the pool
* without threads to handle tasks once they become eligible to run. * without threads to handle tasks once they become eligible to run.
* *
* <p>As with {@code ThreadPoolExecutor}, if not otherwise specified,
* this class uses {@link Executors#defaultThreadFactory} as the
* default thread factory, and {@link ThreadPoolExecutor.AbortPolicy}
* as the default rejected execution handler.
*
* <p><b>Extension notes:</b> This class overrides the * <p><b>Extension notes:</b> This class overrides the
* {@link ThreadPoolExecutor#execute(Runnable) execute} and * {@link ThreadPoolExecutor#execute(Runnable) execute} and
* {@link AbstractExecutorService#submit(Runnable) submit} * {@link AbstractExecutorService#submit(Runnable) submit}
@ -161,7 +167,7 @@ public class ScheduledThreadPoolExecutor
private volatile boolean continueExistingPeriodicTasksAfterShutdown; private volatile boolean continueExistingPeriodicTasksAfterShutdown;
/** /**
* False if should cancel non-periodic tasks on shutdown. * False if should cancel non-periodic not-yet-expired tasks on shutdown.
*/ */
private volatile boolean executeExistingDelayedTasksAfterShutdown = true; private volatile boolean executeExistingDelayedTasksAfterShutdown = true;
@ -292,10 +298,9 @@ public class ScheduledThreadPoolExecutor
* Overrides FutureTask version so as to reset/requeue if periodic. * Overrides FutureTask version so as to reset/requeue if periodic.
*/ */
public void run() { public void run() {
boolean periodic = isPeriodic(); if (!canRunInCurrentRunState(this))
if (!canRunInCurrentRunState(periodic))
cancel(false); cancel(false);
else if (!periodic) else if (!isPeriodic())
super.run(); super.run();
else if (super.runAndReset()) { else if (super.runAndReset()) {
setNextRunTime(); setNextRunTime();
@ -305,15 +310,18 @@ public class ScheduledThreadPoolExecutor
} }
/** /**
* Returns true if can run a task given current run state * Returns true if can run a task given current run state and
* and run-after-shutdown parameters. * run-after-shutdown parameters.
*
* @param periodic true if this task periodic, false if delayed
*/ */
boolean canRunInCurrentRunState(boolean periodic) { boolean canRunInCurrentRunState(RunnableScheduledFuture<?> task) {
return isRunningOrShutdown(periodic ? if (!isShutdown())
continueExistingPeriodicTasksAfterShutdown : return true;
executeExistingDelayedTasksAfterShutdown); if (isStopped())
return false;
return task.isPeriodic()
? continueExistingPeriodicTasksAfterShutdown
: (executeExistingDelayedTasksAfterShutdown
|| task.getDelay(NANOSECONDS) <= 0);
} }
/** /**
@ -332,9 +340,7 @@ public class ScheduledThreadPoolExecutor
reject(task); reject(task);
else { else {
super.getQueue().add(task); super.getQueue().add(task);
if (isShutdown() && if (!canRunInCurrentRunState(task) && remove(task))
!canRunInCurrentRunState(task.isPeriodic()) &&
remove(task))
task.cancel(false); task.cancel(false);
else else
ensurePrestart(); ensurePrestart();
@ -348,14 +354,15 @@ public class ScheduledThreadPoolExecutor
* @param task the task * @param task the task
*/ */
void reExecutePeriodic(RunnableScheduledFuture<?> task) { void reExecutePeriodic(RunnableScheduledFuture<?> task) {
if (canRunInCurrentRunState(true)) { if (canRunInCurrentRunState(task)) {
super.getQueue().add(task); super.getQueue().add(task);
if (!canRunInCurrentRunState(true) && remove(task)) if (canRunInCurrentRunState(task) || !remove(task)) {
task.cancel(false);
else
ensurePrestart(); ensurePrestart();
return;
} }
} }
task.cancel(false);
}
/** /**
* Cancels and clears the queue of all tasks that should not be run * Cancels and clears the queue of all tasks that should not be run
@ -367,26 +374,21 @@ public class ScheduledThreadPoolExecutor
getExecuteExistingDelayedTasksAfterShutdownPolicy(); getExecuteExistingDelayedTasksAfterShutdownPolicy();
boolean keepPeriodic = boolean keepPeriodic =
getContinueExistingPeriodicTasksAfterShutdownPolicy(); getContinueExistingPeriodicTasksAfterShutdownPolicy();
if (!keepDelayed && !keepPeriodic) {
for (Object e : q.toArray())
if (e instanceof RunnableScheduledFuture<?>)
((RunnableScheduledFuture<?>) e).cancel(false);
q.clear();
}
else {
// Traverse snapshot to avoid iterator exceptions // Traverse snapshot to avoid iterator exceptions
// TODO: implement and use efficient removeIf
// super.getQueue().removeIf(...);
for (Object e : q.toArray()) { for (Object e : q.toArray()) {
if (e instanceof RunnableScheduledFuture) { if (e instanceof RunnableScheduledFuture) {
RunnableScheduledFuture<?> t = RunnableScheduledFuture<?> t = (RunnableScheduledFuture<?>)e;
(RunnableScheduledFuture<?>)e; if ((t.isPeriodic()
if ((t.isPeriodic() ? !keepPeriodic : !keepDelayed) || ? !keepPeriodic
t.isCancelled()) { // also remove if already cancelled : (!keepDelayed && t.getDelay(NANOSECONDS) > 0))
|| t.isCancelled()) { // also remove if already cancelled
if (q.remove(t)) if (q.remove(t))
t.cancel(false); t.cancel(false);
} }
} }
} }
}
tryTerminate(); tryTerminate();
} }
@ -579,6 +581,34 @@ public class ScheduledThreadPoolExecutor
} }
/** /**
* Submits a periodic action that becomes enabled first after the
* given initial delay, and subsequently with the given period;
* that is, executions will commence after
* {@code initialDelay}, then {@code initialDelay + period}, then
* {@code initialDelay + 2 * period}, and so on.
*
* <p>The sequence of task executions continues indefinitely until
* one of the following exceptional completions occur:
* <ul>
* <li>The task is {@linkplain Future#cancel explicitly cancelled}
* via the returned future.
* <li>Method {@link #shutdown} is called and the {@linkplain
* #getContinueExistingPeriodicTasksAfterShutdownPolicy policy on
* whether to continue after shutdown} is not set true, or method
* {@link #shutdownNow} is called; also resulting in task
* cancellation.
* <li>An execution of the task throws an exception. In this case
* calling {@link Future#get() get} on the returned future will throw
* {@link ExecutionException}, holding the exception as its cause.
* </ul>
* Subsequent executions are suppressed. Subsequent calls to
* {@link Future#isDone isDone()} on the returned future will
* return {@code true}.
*
* <p>If any execution of this task takes longer than its period, then
* subsequent executions may start late, but will not concurrently
* execute.
*
* @throws RejectedExecutionException {@inheritDoc} * @throws RejectedExecutionException {@inheritDoc}
* @throws NullPointerException {@inheritDoc} * @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc}
@ -604,6 +634,29 @@ public class ScheduledThreadPoolExecutor
} }
/** /**
* Submits a periodic action that becomes enabled first after the
* given initial delay, and subsequently with the given delay
* between the termination of one execution and the commencement of
* the next.
*
* <p>The sequence of task executions continues indefinitely until
* one of the following exceptional completions occur:
* <ul>
* <li>The task is {@linkplain Future#cancel explicitly cancelled}
* via the returned future.
* <li>Method {@link #shutdown} is called and the {@linkplain
* #getContinueExistingPeriodicTasksAfterShutdownPolicy policy on
* whether to continue after shutdown} is not set true, or method
* {@link #shutdownNow} is called; also resulting in task
* cancellation.
* <li>An execution of the task throws an exception. In this case
* calling {@link Future#get() get} on the returned future will throw
* {@link ExecutionException}, holding the exception as its cause.
* </ul>
* Subsequent executions are suppressed. Subsequent calls to
* {@link Future#isDone isDone()} on the returned future will
* return {@code true}.
*
* @throws RejectedExecutionException {@inheritDoc} * @throws RejectedExecutionException {@inheritDoc}
* @throws NullPointerException {@inheritDoc} * @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc}
@ -681,9 +734,8 @@ public class ScheduledThreadPoolExecutor
/** /**
* Sets the policy on whether to continue executing existing * Sets the policy on whether to continue executing existing
* periodic tasks even when this executor has been {@code shutdown}. * periodic tasks even when this executor has been {@code shutdown}.
* In this case, these tasks will only terminate upon * In this case, executions will continue until {@code shutdownNow}
* {@code shutdownNow} or after setting the policy to * or the policy is set to {@code false} when already shutdown.
* {@code false} when already shutdown.
* This value is by default {@code false}. * This value is by default {@code false}.
* *
* @param value if {@code true}, continue after shutdown, else don't * @param value if {@code true}, continue after shutdown, else don't
@ -698,9 +750,8 @@ public class ScheduledThreadPoolExecutor
/** /**
* Gets the policy on whether to continue executing existing * Gets the policy on whether to continue executing existing
* periodic tasks even when this executor has been {@code shutdown}. * periodic tasks even when this executor has been {@code shutdown}.
* In this case, these tasks will only terminate upon * In this case, executions will continue until {@code shutdownNow}
* {@code shutdownNow} or after setting the policy to * or the policy is set to {@code false} when already shutdown.
* {@code false} when already shutdown.
* This value is by default {@code false}. * This value is by default {@code false}.
* *
* @return {@code true} if will continue after shutdown * @return {@code true} if will continue after shutdown
@ -904,7 +955,7 @@ public class ScheduledThreadPoolExecutor
/** /**
* Sets f's heapIndex if it is a ScheduledFutureTask. * Sets f's heapIndex if it is a ScheduledFutureTask.
*/ */
private void setIndex(RunnableScheduledFuture<?> f, int idx) { private static void setIndex(RunnableScheduledFuture<?> f, int idx) {
if (f instanceof ScheduledFutureTask) if (f instanceof ScheduledFutureTask)
((ScheduledFutureTask)f).heapIndex = idx; ((ScheduledFutureTask)f).heapIndex = idx;
} }
@ -1202,41 +1253,12 @@ public class ScheduledThreadPoolExecutor
} }
} }
/**
* Returns first element only if it is expired.
* Used only by drainTo. Call only when holding lock.
*/
private RunnableScheduledFuture<?> peekExpired() {
// assert lock.isHeldByCurrentThread();
RunnableScheduledFuture<?> first = queue[0];
return (first == null || first.getDelay(NANOSECONDS) > 0) ?
null : first;
}
public int drainTo(Collection<? super Runnable> c) { public int drainTo(Collection<? super Runnable> 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 {
RunnableScheduledFuture<?> first;
int n = 0;
while ((first = peekExpired()) != null) {
c.add(first); // In this order, in case add() throws.
finishPoll(first);
++n;
}
return n;
} finally {
lock.unlock();
}
} }
public int drainTo(Collection<? super Runnable> c, int maxElements) { public int drainTo(Collection<? super Runnable> c, int maxElements) {
if (c == null) Objects.requireNonNull(c);
throw new NullPointerException();
if (c == this) if (c == this)
throw new IllegalArgumentException(); throw new IllegalArgumentException();
if (maxElements <= 0) if (maxElements <= 0)
@ -1244,9 +1266,11 @@ public class ScheduledThreadPoolExecutor
final ReentrantLock lock = this.lock; final ReentrantLock lock = this.lock;
lock.lock(); lock.lock();
try { try {
RunnableScheduledFuture<?> first;
int n = 0; int n = 0;
while (n < maxElements && (first = peekExpired()) != null) { for (RunnableScheduledFuture<?> first;
n < maxElements
&& (first = queue[0]) != null
&& first.getDelay(NANOSECONDS) <= 0;) {
c.add(first); // In this order, in case add() throws. c.add(first); // In this order, in case add() throws.
finishPoll(first); finishPoll(first);
++n; ++n;
@ -1284,7 +1308,13 @@ public class ScheduledThreadPoolExecutor
} }
public Iterator<Runnable> iterator() { public Iterator<Runnable> iterator() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return new Itr(Arrays.copyOf(queue, size)); return new Itr(Arrays.copyOf(queue, size));
} finally {
lock.unlock();
}
} }
/** /**

View File

@ -1066,7 +1066,7 @@ public class SynchronousQueue<E> extends AbstractQueue<E>
/** /**
* Returns an empty spliterator in which calls to * Returns an empty spliterator in which calls to
* {@link java.util.Spliterator#trySplit()} always return {@code null}. * {@link Spliterator#trySplit() trySplit} always return {@code null}.
* *
* @return an empty spliterator * @return an empty spliterator
* @since 1.8 * @since 1.8

View File

@ -74,31 +74,28 @@ import java.util.concurrent.locks.ReentrantLock;
* *
* <dt>Core and maximum pool sizes</dt> * <dt>Core and maximum pool sizes</dt>
* *
* <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif"> * <dd>A {@code ThreadPoolExecutor} will automatically adjust the
* A {@code ThreadPoolExecutor} will automatically adjust the
* pool size (see {@link #getPoolSize}) * pool size (see {@link #getPoolSize})
* according to the bounds set by * according to the bounds set by
* corePoolSize (see {@link #getCorePoolSize}) and * corePoolSize (see {@link #getCorePoolSize}) and
* maximumPoolSize (see {@link #getMaximumPoolSize}). * maximumPoolSize (see {@link #getMaximumPoolSize}).
* *
* When a new task is submitted in method {@link #execute(Runnable)}, * When a new task is submitted in method {@link #execute(Runnable)},
* and fewer than corePoolSize threads are running, a new thread is * if fewer than corePoolSize threads are running, a new thread is
* created to handle the request, even if other worker threads are * created to handle the request, even if other worker threads are
* idle. If there are more than corePoolSize but less than * idle. Else if fewer than maximumPoolSize threads are running, a
* maximumPoolSize threads running, a new thread will be created only * new thread will be created to handle the request only if the queue
* if the queue is full. By setting corePoolSize and maximumPoolSize * is full. By setting corePoolSize and maximumPoolSize the same, you
* the same, you create a fixed-size thread pool. By setting * create a fixed-size thread pool. By setting maximumPoolSize to an
* maximumPoolSize to an essentially unbounded value such as {@code * essentially unbounded value such as {@code Integer.MAX_VALUE}, you
* Integer.MAX_VALUE}, you allow the pool to accommodate an arbitrary * allow the pool to accommodate an arbitrary number of concurrent
* number of concurrent tasks. Most typically, core and maximum pool * tasks. Most typically, core and maximum pool sizes are set only
* sizes are set only upon construction, but they may also be changed * upon construction, but they may also be changed dynamically using
* dynamically using {@link #setCorePoolSize} and {@link * {@link #setCorePoolSize} and {@link #setMaximumPoolSize}. </dd>
* #setMaximumPoolSize}. </dd>
* *
* <dt>On-demand construction</dt> * <dt>On-demand construction</dt>
* *
* <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif"> * <dd>By default, even core threads are initially created and
* By default, even core threads are initially created and
* started only when new tasks arrive, but this can be overridden * started only when new tasks arrive, but this can be overridden
* dynamically using method {@link #prestartCoreThread} or {@link * dynamically using method {@link #prestartCoreThread} or {@link
* #prestartAllCoreThreads}. You probably want to prestart threads if * #prestartAllCoreThreads}. You probably want to prestart threads if
@ -106,8 +103,7 @@ import java.util.concurrent.locks.ReentrantLock;
* *
* <dt>Creating new threads</dt> * <dt>Creating new threads</dt>
* *
* <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif"> * <dd>New threads are created using a {@link ThreadFactory}. If not
* New threads are created using a {@link ThreadFactory}. If not
* otherwise specified, a {@link Executors#defaultThreadFactory} is * otherwise specified, a {@link Executors#defaultThreadFactory} is
* used, that creates threads to all be in the same {@link * used, that creates threads to all be in the same {@link
* ThreadGroup} and with the same {@code NORM_PRIORITY} priority and * ThreadGroup} and with the same {@code NORM_PRIORITY} priority and
@ -124,8 +120,7 @@ import java.util.concurrent.locks.ReentrantLock;
* *
* <dt>Keep-alive times</dt> * <dt>Keep-alive times</dt>
* *
* <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif"> * <dd>If the pool currently has more than corePoolSize threads,
* If the pool currently has more than corePoolSize threads,
* excess threads will be terminated if they have been idle for more * excess threads will be terminated if they have been idle for more
* than the keepAliveTime (see {@link #getKeepAliveTime(TimeUnit)}). * than the keepAliveTime (see {@link #getKeepAliveTime(TimeUnit)}).
* This provides a means of reducing resource consumption when the * This provides a means of reducing resource consumption when the
@ -142,8 +137,7 @@ import java.util.concurrent.locks.ReentrantLock;
* *
* <dt>Queuing</dt> * <dt>Queuing</dt>
* *
* <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif"> * <dd>Any {@link BlockingQueue} may be used to transfer and hold
* Any {@link BlockingQueue} may be used to transfer and hold
* submitted tasks. The use of this queue interacts with pool sizing: * submitted tasks. The use of this queue interacts with pool sizing:
* *
* <ul> * <ul>
@ -208,8 +202,7 @@ import java.util.concurrent.locks.ReentrantLock;
* *
* <dt>Rejected tasks</dt> * <dt>Rejected tasks</dt>
* *
* <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif"> * <dd>New tasks submitted in method {@link #execute(Runnable)} will be
* New tasks submitted in method {@link #execute(Runnable)} will be
* <em>rejected</em> when the Executor has been shut down, and also when * <em>rejected</em> when the Executor has been shut down, and also when
* the Executor uses finite bounds for both maximum threads and work queue * the Executor uses finite bounds for both maximum threads and work queue
* capacity, and is saturated. In either case, the {@code execute} method * capacity, and is saturated. In either case, the {@code execute} method
@ -220,9 +213,8 @@ import java.util.concurrent.locks.ReentrantLock;
* *
* <ol> * <ol>
* *
* <li>In the default {@link ThreadPoolExecutor.AbortPolicy}, the * <li>In the default {@link ThreadPoolExecutor.AbortPolicy}, the handler
* handler throws a runtime {@link RejectedExecutionException} upon * throws a runtime {@link RejectedExecutionException} upon rejection.
* rejection.
* *
* <li>In {@link ThreadPoolExecutor.CallerRunsPolicy}, the thread * <li>In {@link ThreadPoolExecutor.CallerRunsPolicy}, the thread
* that invokes {@code execute} itself runs the task. This provides a * that invokes {@code execute} itself runs the task. This provides a
@ -246,8 +238,7 @@ import java.util.concurrent.locks.ReentrantLock;
* *
* <dt>Hook methods</dt> * <dt>Hook methods</dt>
* *
* <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif"> * <dd>This class provides {@code protected} overridable
* This class provides {@code protected} overridable
* {@link #beforeExecute(Thread, Runnable)} and * {@link #beforeExecute(Thread, Runnable)} and
* {@link #afterExecute(Runnable, Throwable)} methods that are called * {@link #afterExecute(Runnable, Throwable)} methods that are called
* before and after execution of each task. These can be used to * before and after execution of each task. These can be used to
@ -263,8 +254,7 @@ import java.util.concurrent.locks.ReentrantLock;
* *
* <dt>Queue maintenance</dt> * <dt>Queue maintenance</dt>
* *
* <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif"> * <dd>Method {@link #getQueue()} allows access to the work queue
* Method {@link #getQueue()} allows access to the work queue
* for purposes of monitoring and debugging. Use of this method for * for purposes of monitoring and debugging. Use of this method for
* any other purpose is strongly discouraged. Two supplied methods, * any other purpose is strongly discouraged. Two supplied methods,
* {@link #remove(Runnable)} and {@link #purge} are available to * {@link #remove(Runnable)} and {@link #purge} are available to
@ -273,8 +263,7 @@ import java.util.concurrent.locks.ReentrantLock;
* *
* <dt>Finalization</dt> * <dt>Finalization</dt>
* *
* <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif"> * <dd>A pool that is no longer referenced in a program <em>AND</em>
* A pool that is no longer referenced in a program <em>AND</em>
* has no remaining threads will be {@code shutdown} automatically. If * has no remaining threads will be {@code shutdown} automatically. If
* you would like to ensure that unreferenced pools are reclaimed even * you would like to ensure that unreferenced pools are reclaimed even
* if users forget to call {@link #shutdown}, then you must arrange * if users forget to call {@link #shutdown}, then you must arrange
@ -850,17 +839,6 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
void onShutdown() { void onShutdown() {
} }
/**
* State check needed by ScheduledThreadPoolExecutor to
* enable running tasks during shutdown.
*
* @param shutdownOK true if should return true if SHUTDOWN
*/
final boolean isRunningOrShutdown(boolean shutdownOK) {
int rs = runStateOf(ctl.get());
return rs == RUNNING || (rs == SHUTDOWN && shutdownOK);
}
/** /**
* Drains the task queue into a new list, normally using * Drains the task queue into a new list, normally using
* drainTo. But if the queue is a DelayQueue or any other kind of * drainTo. But if the queue is a DelayQueue or any other kind of
@ -1184,9 +1162,11 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
/** /**
* Creates a new {@code ThreadPoolExecutor} with the given initial * Creates a new {@code ThreadPoolExecutor} with the given initial
* parameters and default thread factory and rejected execution handler. * parameters, the default thread factory and the default rejected
* It may be more convenient to use one of the {@link Executors} factory * execution handler.
* methods instead of this general purpose constructor. *
* <p>It may be more convenient to use one of the {@link Executors}
* factory methods instead of this general purpose constructor.
* *
* @param corePoolSize the number of threads to keep in the pool, even * @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set * if they are idle, unless {@code allowCoreThreadTimeOut} is set
@ -1217,7 +1197,8 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
/** /**
* Creates a new {@code ThreadPoolExecutor} with the given initial * Creates a new {@code ThreadPoolExecutor} with the given initial
* parameters and default rejected execution handler. * parameters and {@linkplain ThreadPoolExecutor.AbortPolicy
* default rejected execution handler}.
* *
* @param corePoolSize the number of threads to keep in the pool, even * @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set * if they are idle, unless {@code allowCoreThreadTimeOut} is set
@ -1252,7 +1233,8 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
/** /**
* Creates a new {@code ThreadPoolExecutor} with the given initial * Creates a new {@code ThreadPoolExecutor} with the given initial
* parameters and default thread factory. * parameters and
* {@linkplain Executors#defaultThreadFactory default thread factory}.
* *
* @param corePoolSize the number of threads to keep in the pool, even * @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set * if they are idle, unless {@code allowCoreThreadTimeOut} is set
@ -1450,6 +1432,11 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
return ! isRunning(ctl.get()); return ! isRunning(ctl.get());
} }
/** Used by ScheduledThreadPoolExecutor. */
boolean isStopped() {
return runStateAtLeast(ctl.get(), STOP);
}
/** /**
* Returns true if this executor is in the process of terminating * Returns true if this executor is in the process of terminating
* after {@link #shutdown} or {@link #shutdownNow} but has not * after {@link #shutdown} or {@link #shutdownNow} but has not
@ -2065,7 +2052,10 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
/** /**
* A handler for rejected tasks that throws a * A handler for rejected tasks that throws a
* {@code RejectedExecutionException}. * {@link RejectedExecutionException}.
*
* This is the default handler for {@link ThreadPoolExecutor} and
* {@link ScheduledThreadPoolExecutor}.
*/ */
public static class AbortPolicy implements RejectedExecutionHandler { public static class AbortPolicy implements RejectedExecutionHandler {
/** /**

View File

@ -337,8 +337,8 @@ public enum TimeUnit {
* This is a convenience method that converts timeout arguments * This is a convenience method that converts timeout arguments
* into the form required by the {@code Object.wait} method. * into the form required by the {@code Object.wait} method.
* *
* <p>For example, you could implement a blocking {@code poll} * <p>For example, you could implement a blocking {@code poll} method
* method (see {@link BlockingQueue#poll BlockingQueue.poll}) * (see {@link BlockingQueue#poll(long, TimeUnit) BlockingQueue.poll})
* using: * using:
* *
* <pre> {@code * <pre> {@code

View File

@ -56,11 +56,13 @@ import java.util.function.DoubleBinaryOperator;
* *
* <p>The supplied accumulator function should be side-effect-free, * <p>The supplied accumulator function should be side-effect-free,
* since it may be re-applied when attempted updates fail due to * since it may be re-applied when attempted updates fail due to
* contention among threads. The function is applied with the current * contention among threads. For predictable results, the accumulator
* value as its first argument, and the given update as the second * function should be commutative and associative within the floating
* argument. For example, to maintain a running maximum value, you * point tolerance required in usage contexts. The function is applied
* could supply {@code Double::max} along with {@code * with an existing value (or identity) as one argument, and a given
* Double.NEGATIVE_INFINITY} as the identity. The order of * update as the other argument. For example, to maintain a running
* maximum value, you could supply {@code Double::max} along with
* {@code Double.NEGATIVE_INFINITY} as the identity. The order of
* accumulation within or across threads is not guaranteed. Thus, this * accumulation within or across threads is not guaranteed. Thus, this
* class may not be applicable if numerical stability is required, * class may not be applicable if numerical stability is required,
* especially when combining values of substantially different orders * especially when combining values of substantially different orders

View File

@ -59,11 +59,12 @@ import java.util.function.LongBinaryOperator;
* applicable to functions for which the order of accumulation does * applicable to functions for which the order of accumulation does
* not matter. The supplied accumulator function should be * not matter. The supplied accumulator function should be
* side-effect-free, since it may be re-applied when attempted updates * side-effect-free, since it may be re-applied when attempted updates
* fail due to contention among threads. The function is applied with * fail due to contention among threads. For predictable results, the
* the current value as its first argument, and the given update as * accumulator function should be associative and commutative. The
* the second argument. For example, to maintain a running maximum * function is applied with an existing value (or identity) as one
* value, you could supply {@code Long::max} along with {@code * argument, and a given update as the other argument. For example,
* Long.MIN_VALUE} as the identity. * to maintain a running maximum value, you could supply {@code
* Long::max} along with {@code Long.MIN_VALUE} as the identity.
* *
* <p>Class {@link LongAdder} provides analogs of the functionality of * <p>Class {@link LongAdder} provides analogs of the functionality of
* this class for the common special case of maintaining counts and * this class for the common special case of maintaining counts and

View File

@ -113,8 +113,7 @@ public abstract class AbstractQueuedLongSynchronizer
* @param newState the new state value * @param newState the new state value
*/ */
protected final void setState(long newState) { protected final void setState(long newState) {
// Use putLongVolatile instead of ordinary volatile store when // See JDK-8180620: Clarify VarHandle mixed-access subtleties
// using compareAndSwapLong, for sake of some 32bit systems.
STATE.setVolatile(this, newState); STATE.setVolatile(this, newState);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2009, 2017 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
@ -40,17 +40,18 @@ public class IOUtils {
* Read up to <code>length</code> of bytes from <code>in</code> * Read up to <code>length</code> of bytes from <code>in</code>
* until EOF is detected. * until EOF is detected.
* @param is input stream, must not be null * @param is input stream, must not be null
* @param length number of bytes to read, -1 or Integer.MAX_VALUE means * @param length number of bytes to read
* read as much as possible
* @param readAll if true, an EOFException will be thrown if not enough * @param readAll if true, an EOFException will be thrown if not enough
* bytes are read. Ignored when length is -1 or Integer.MAX_VALUE * bytes are read.
* @return bytes read * @return bytes read
* @throws IOException Any IO error or a premature EOF is detected * @throws IOException Any IO error or a premature EOF is detected
*/ */
public static byte[] readFully(InputStream is, int length, boolean readAll) public static byte[] readFully(InputStream is, int length, boolean readAll)
throws IOException { throws IOException {
if (length < 0) {
throw new IOException("Invalid length");
}
byte[] output = {}; byte[] output = {};
if (length == -1) length = Integer.MAX_VALUE;
int pos = 0; int pos = 0;
while (pos < length) { while (pos < length) {
int bytesToRead; int bytesToRead;
@ -64,7 +65,7 @@ public class IOUtils {
} }
int cc = is.read(output, pos, bytesToRead); int cc = is.read(output, pos, bytesToRead);
if (cc < 0) { if (cc < 0) {
if (readAll && length != Integer.MAX_VALUE) { if (readAll) {
throw new EOFException("Detect premature EOF"); throw new EOFException("Detect premature EOF");
} else { } else {
if (output.length != pos) { if (output.length != pos) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2017, 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
@ -137,7 +137,7 @@ import sun.reflect.misc.ReflectUtil;
* <code>MalformedURLException</code> if there is none. An * <code>MalformedURLException</code> if there is none. An
* implementation may choose to find providers by other means. For * implementation may choose to find providers by other means. For
* example, it may support <a * example, it may support <a
* href="{@docRoot}/../java/util/ServiceLoader.html#developing-service-providers">service providers</a>, * href="{@docRoot}/java/util/ServiceLoader.html#developing-service-providers">service providers</a>,
* where the service interface is <code>JMXConnectorProvider</code>.</p> * where the service interface is <code>JMXConnectorProvider</code>.</p>
* *
* <p>Every implementation must support the RMI connector protocol with * <p>Every implementation must support the RMI connector protocol with

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2017, 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
@ -128,7 +128,7 @@ import javax.management.remote.JMXConnectorFactory.ConnectorFactory;
* <code>MalformedURLException</code> if there is none. An * <code>MalformedURLException</code> if there is none. An
* implementation may choose to find providers by other means. For * implementation may choose to find providers by other means. For
* example, it may support <a * example, it may support <a
* href="{@docRoot}/../java/util/ServiceLoader.html#developing-service-providers">service providers</a>, * href="{@docRoot}/java/util/ServiceLoader.html#developing-service-providers">service providers</a>,
* where the service interface is <code>JMXConnectorServerProvider</code>.</p> * where the service interface is <code>JMXConnectorServerProvider</code>.</p>
* *
* <p>Every implementation must support the RMI connector protocol with * <p>Every implementation must support the RMI connector protocol with

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2017, 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
@ -31,7 +31,6 @@
* object registry, and the <em>{@index rmid rmid tool}</em> tool to start * object registry, and the <em>{@index rmid rmid tool}</em> tool to start
* the activation system daemon. * the activation system daemon.
* *
* <p>
* <dl style="font-family:'DejaVu Sans', Arial, Helvetica, sans serif"> * <dl style="font-family:'DejaVu Sans', Arial, Helvetica, sans serif">
* <dt class="simpleTagLabel">Tool Guides:</dt> * <dt class="simpleTagLabel">Tool Guides:</dt>
* <dd> {@extLink rmiregistry_tool_reference rmiregistry}, * <dd> {@extLink rmiregistry_tool_reference rmiregistry},

View File

@ -56,6 +56,7 @@ import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.LongAdder;
import java.util.regex.Pattern; import java.util.regex.Pattern;
/** /**
@ -391,16 +392,53 @@ public class IteratorMicroBenchmark {
for (Integer o : x.toArray(empty)) for (Integer o : x.toArray(empty))
sum[0] += o; sum[0] += o;
check.sum(sum[0]);}}}, check.sum(sum[0]);}}},
new Job(klazz + " stream().forEach") {
public void work() throws Throwable {
int[] sum = new int[1];
for (int i = 0; i < iterations; i++) {
sum[0] = 0;
x.stream().forEach(n -> sum[0] += n);
check.sum(sum[0]);}}},
new Job(klazz + " stream().mapToInt") {
public void work() throws Throwable {
for (int i = 0; i < iterations; i++) {
check.sum(x.stream().mapToInt(e -> e).sum());}}},
new Job(klazz + " stream().collect") { new Job(klazz + " stream().collect") {
public void work() throws Throwable { public void work() throws Throwable {
for (int i = 0; i < iterations; i++) { for (int i = 0; i < iterations; i++) {
check.sum(x.stream() check.sum(x.stream()
.collect(summingInt(e -> e)));}}}, .collect(summingInt(e -> e)));}}},
new Job(klazz + " stream()::iterator") {
public void work() throws Throwable {
int[] sum = new int[1];
for (int i = 0; i < iterations; i++) {
sum[0] = 0;
for (Integer o : (Iterable<Integer>) x.stream()::iterator)
sum[0] += o;
check.sum(sum[0]);}}},
new Job(klazz + " parallelStream().forEach") {
public void work() throws Throwable {
for (int i = 0; i < iterations; i++) {
LongAdder sum = new LongAdder();
x.parallelStream().forEach(n -> sum.add(n));
check.sum((int) sum.sum());}}},
new Job(klazz + " parallelStream().mapToInt") {
public void work() throws Throwable {
for (int i = 0; i < iterations; i++) {
check.sum(x.parallelStream().mapToInt(e -> e).sum());}}},
new Job(klazz + " parallelStream().collect") { new Job(klazz + " parallelStream().collect") {
public void work() throws Throwable { public void work() throws Throwable {
for (int i = 0; i < iterations; i++) { for (int i = 0; i < iterations; i++) {
check.sum(x.parallelStream() check.sum(x.parallelStream()
.collect(summingInt(e -> e)));}}}); .collect(summingInt(e -> e)));}}},
new Job(klazz + " parallelStream()::iterator") {
public void work() throws Throwable {
int[] sum = new int[1];
for (int i = 0; i < iterations; i++) {
sum[0] = 0;
for (Integer o : (Iterable<Integer>) x.parallelStream()::iterator)
sum[0] += o;
check.sum(sum[0]);}}});
} }
List<Job> dequeJobs(Deque<Integer> x) { List<Job> dequeJobs(Deque<Integer> x) {

View File

@ -38,6 +38,7 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.AbstractExecutorService; import java.util.concurrent.AbstractExecutorService;
@ -192,25 +193,13 @@ public class AbstractExecutorServiceTest extends JSR166TestCase {
} }
/** /**
* execute(null runnable) throws NPE * Submitting null tasks throws NullPointerException
*/ */
public void testExecuteNullRunnable() { public void testNullTaskSubmission() {
ExecutorService e = new DirectExecutorService(); final ExecutorService e = new DirectExecutorService();
try { try (PoolCleaner cleaner = cleaner(e)) {
e.submit((Runnable) null); assertNullTaskSubmissionThrowsNullPointerException(e);
shouldThrow();
} catch (NullPointerException success) {}
} }
/**
* submit(null callable) throws NPE
*/
public void testSubmitNullCallable() {
ExecutorService e = new DirectExecutorService();
try {
e.submit((Callable) null);
shouldThrow();
} catch (NullPointerException success) {}
} }
/** /**
@ -276,13 +265,15 @@ public class AbstractExecutorServiceTest extends JSR166TestCase {
} }
/** /**
* invokeAny(empty collection) throws IAE * invokeAny(empty collection) throws IllegalArgumentException
*/ */
public void testInvokeAny2() throws Exception { public void testInvokeAny2() throws Exception {
final ExecutorService e = new DirectExecutorService(); final ExecutorService e = new DirectExecutorService();
final Collection<Callable<String>> emptyCollection
= Collections.emptyList();
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
try { try {
e.invokeAny(new ArrayList<Callable<String>>()); e.invokeAny(emptyCollection);
shouldThrow(); shouldThrow();
} catch (IllegalArgumentException success) {} } catch (IllegalArgumentException success) {}
} }
@ -350,12 +341,14 @@ public class AbstractExecutorServiceTest extends JSR166TestCase {
} }
/** /**
* invokeAll(empty collection) returns empty collection * invokeAll(empty collection) returns empty list
*/ */
public void testInvokeAll2() throws InterruptedException { public void testInvokeAll2() throws InterruptedException {
final ExecutorService e = new DirectExecutorService(); final ExecutorService e = new DirectExecutorService();
final Collection<Callable<String>> emptyCollection
= Collections.emptyList();
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>()); List<Future<String>> r = e.invokeAll(emptyCollection);
assertTrue(r.isEmpty()); assertTrue(r.isEmpty());
} }
} }
@ -418,14 +411,14 @@ public class AbstractExecutorServiceTest extends JSR166TestCase {
final ExecutorService e = new DirectExecutorService(); final ExecutorService e = new DirectExecutorService();
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
try { try {
e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAny(null, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
} }
/** /**
* timed invokeAny(null time unit) throws NPE * timed invokeAny(null time unit) throws NullPointerException
*/ */
public void testTimedInvokeAnyNullTimeUnit() throws Exception { public void testTimedInvokeAnyNullTimeUnit() throws Exception {
final ExecutorService e = new DirectExecutorService(); final ExecutorService e = new DirectExecutorService();
@ -433,21 +426,22 @@ public class AbstractExecutorServiceTest extends JSR166TestCase {
List<Callable<String>> l = new ArrayList<>(); List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask()); l.add(new StringTask());
try { try {
e.invokeAny(l, MEDIUM_DELAY_MS, null); e.invokeAny(l, randomTimeout(), null);
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
} }
/** /**
* timed invokeAny(empty collection) throws IAE * timed invokeAny(empty collection) throws IllegalArgumentException
*/ */
public void testTimedInvokeAny2() throws Exception { public void testTimedInvokeAny2() throws Exception {
final ExecutorService e = new DirectExecutorService(); final ExecutorService e = new DirectExecutorService();
final Collection<Callable<String>> emptyCollection
= Collections.emptyList();
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
try { try {
e.invokeAny(new ArrayList<Callable<String>>(), e.invokeAny(emptyCollection, randomTimeout(), randomTimeUnit());
MEDIUM_DELAY_MS, MILLISECONDS);
shouldThrow(); shouldThrow();
} catch (IllegalArgumentException success) {} } catch (IllegalArgumentException success) {}
} }
@ -464,7 +458,7 @@ public class AbstractExecutorServiceTest extends JSR166TestCase {
public Long call() { throw new ArithmeticException(); }}); public Long call() { throw new ArithmeticException(); }});
l.add(null); l.add(null);
try { try {
e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAny(l, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
@ -506,13 +500,13 @@ public class AbstractExecutorServiceTest extends JSR166TestCase {
} }
/** /**
* timed invokeAll(null) throws NPE * timed invokeAll(null) throws NullPointerException
*/ */
public void testTimedInvokeAll1() throws InterruptedException { public void testTimedInvokeAll1() throws InterruptedException {
final ExecutorService e = new DirectExecutorService(); final ExecutorService e = new DirectExecutorService();
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
try { try {
e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAll(null, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
@ -527,25 +521,28 @@ public class AbstractExecutorServiceTest extends JSR166TestCase {
List<Callable<String>> l = new ArrayList<>(); List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask()); l.add(new StringTask());
try { try {
e.invokeAll(l, MEDIUM_DELAY_MS, null); e.invokeAll(l, randomTimeout(), null);
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
} }
/** /**
* timed invokeAll(empty collection) returns empty collection * timed invokeAll(empty collection) returns empty list
*/ */
public void testTimedInvokeAll2() throws InterruptedException { public void testTimedInvokeAll2() throws InterruptedException {
final ExecutorService e = new DirectExecutorService(); final ExecutorService e = new DirectExecutorService();
final Collection<Callable<String>> emptyCollection
= Collections.emptyList();
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS); List<Future<String>> r =
e.invokeAll(emptyCollection, randomTimeout(), randomTimeUnit());
assertTrue(r.isEmpty()); assertTrue(r.isEmpty());
} }
} }
/** /**
* timed invokeAll(c) throws NPE if c has null elements * timed invokeAll(c) throws NullPointerException if c has null elements
*/ */
public void testTimedInvokeAll3() throws InterruptedException { public void testTimedInvokeAll3() throws InterruptedException {
final ExecutorService e = new DirectExecutorService(); final ExecutorService e = new DirectExecutorService();
@ -554,7 +551,7 @@ public class AbstractExecutorServiceTest extends JSR166TestCase {
l.add(new StringTask()); l.add(new StringTask());
l.add(null); l.add(null);
try { try {
e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAll(l, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }

View File

@ -80,7 +80,7 @@ public class AbstractQueueTest extends JSR166TestCase {
} }
/** /**
* add throws ISE true if offer fails * add throws IllegalStateException true if offer fails
*/ */
public void testAddF() { public void testAddF() {
Fail q = new Fail(); Fail q = new Fail();
@ -91,7 +91,7 @@ public class AbstractQueueTest extends JSR166TestCase {
} }
/** /**
* add throws NPE if offer does * add throws NullPointerException if offer does
*/ */
public void testAddNPE() { public void testAddNPE() {
Succeed q = new Succeed(); Succeed q = new Succeed();
@ -140,7 +140,7 @@ public class AbstractQueueTest extends JSR166TestCase {
} }
/** /**
* addAll(null) throws NPE * addAll(null) throws NullPointerException
*/ */
public void testAddAll1() { public void testAddAll1() {
Succeed q = new Succeed(); Succeed q = new Succeed();
@ -151,7 +151,7 @@ public class AbstractQueueTest extends JSR166TestCase {
} }
/** /**
* addAll(this) throws IAE * addAll(this) throws IllegalArgumentException
*/ */
public void testAddAllSelf() { public void testAddAllSelf() {
Succeed q = new Succeed(); Succeed q = new Succeed();
@ -162,7 +162,7 @@ public class AbstractQueueTest extends JSR166TestCase {
} }
/** /**
* addAll of a collection with null elements throws NPE * addAll of a collection with null elements throws NullPointerException
*/ */
public void testAddAll2() { public void testAddAll2() {
Succeed q = new Succeed(); Succeed q = new Succeed();
@ -189,7 +189,7 @@ public class AbstractQueueTest extends JSR166TestCase {
} }
/** /**
* addAll throws ISE if an add fails * addAll throws IllegalStateException if an add fails
*/ */
public void testAddAll4() { public void testAddAll4() {
Fail q = new Fail(); Fail q = new Fail();

View File

@ -46,6 +46,7 @@ import junit.framework.AssertionFailedError;
import junit.framework.Test; import junit.framework.Test;
import junit.framework.TestSuite; import junit.framework.TestSuite;
@SuppressWarnings("WaitNotInLoop") // we implement spurious-wakeup freedom
public class AbstractQueuedLongSynchronizerTest extends JSR166TestCase { public class AbstractQueuedLongSynchronizerTest extends JSR166TestCase {
public static void main(String[] args) { public static void main(String[] args) {
main(suite(), args); main(suite(), args);
@ -992,30 +993,30 @@ public class AbstractQueuedLongSynchronizerTest extends JSR166TestCase {
*/ */
public void testAwaitUninterruptibly() { public void testAwaitUninterruptibly() {
final Mutex sync = new Mutex(); final Mutex sync = new Mutex();
final ConditionObject c = sync.newCondition(); final ConditionObject condition = sync.newCondition();
final BooleanLatch pleaseInterrupt = new BooleanLatch(); final BooleanLatch pleaseInterrupt = new BooleanLatch();
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() { public void realRun() {
sync.acquire(); sync.acquire();
assertTrue(pleaseInterrupt.releaseShared(0)); assertTrue(pleaseInterrupt.releaseShared(0));
c.awaitUninterruptibly(); condition.awaitUninterruptibly();
assertTrue(Thread.interrupted()); assertTrue(Thread.interrupted());
assertHasWaitersLocked(sync, c, NO_THREADS); assertHasWaitersLocked(sync, condition, NO_THREADS);
sync.release(); sync.release();
}}); }});
pleaseInterrupt.acquireShared(0); pleaseInterrupt.acquireShared(0);
sync.acquire(); sync.acquire();
assertHasWaitersLocked(sync, c, t); assertHasWaitersLocked(sync, condition, t);
sync.release(); sync.release();
t.interrupt(); t.interrupt();
assertHasWaitersUnlocked(sync, c, t); assertHasWaitersUnlocked(sync, condition, t);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
sync.acquire(); sync.acquire();
assertHasWaitersLocked(sync, c, t); assertHasWaitersLocked(sync, condition, t);
assertHasExclusiveQueuedThreads(sync, NO_THREADS); assertHasExclusiveQueuedThreads(sync, NO_THREADS);
c.signal(); condition.signal();
assertHasWaitersLocked(sync, c, NO_THREADS); assertHasWaitersLocked(sync, condition, NO_THREADS);
assertHasExclusiveQueuedThreads(sync, t); assertHasExclusiveQueuedThreads(sync, t);
sync.release(); sync.release();
awaitTermination(t); awaitTermination(t);
@ -1158,7 +1159,7 @@ public class AbstractQueuedLongSynchronizerTest extends JSR166TestCase {
waitForQueuedThread(l, t); waitForQueuedThread(l, t);
assertFalse(l.isSignalled()); assertFalse(l.isSignalled());
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
assertHasSharedQueuedThreads(l, t); assertHasSharedQueuedThreads(l, t);
assertTrue(l.releaseShared(0)); assertTrue(l.releaseShared(0));
assertTrue(l.isSignalled()); assertTrue(l.isSignalled());
@ -1183,7 +1184,7 @@ public class AbstractQueuedLongSynchronizerTest extends JSR166TestCase {
waitForQueuedThread(l, t); waitForQueuedThread(l, t);
assertFalse(l.isSignalled()); assertFalse(l.isSignalled());
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
assertTrue(l.releaseShared(0)); assertTrue(l.releaseShared(0));
assertTrue(l.isSignalled()); assertTrue(l.isSignalled());
awaitTermination(t); awaitTermination(t);

View File

@ -46,6 +46,7 @@ import junit.framework.AssertionFailedError;
import junit.framework.Test; import junit.framework.Test;
import junit.framework.TestSuite; import junit.framework.TestSuite;
@SuppressWarnings("WaitNotInLoop") // we implement spurious-wakeup freedom
public class AbstractQueuedSynchronizerTest extends JSR166TestCase { public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
public static void main(String[] args) { public static void main(String[] args) {
main(suite(), args); main(suite(), args);
@ -995,30 +996,30 @@ public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
*/ */
public void testAwaitUninterruptibly() { public void testAwaitUninterruptibly() {
final Mutex sync = new Mutex(); final Mutex sync = new Mutex();
final ConditionObject c = sync.newCondition(); final ConditionObject condition = sync.newCondition();
final BooleanLatch pleaseInterrupt = new BooleanLatch(); final BooleanLatch pleaseInterrupt = new BooleanLatch();
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() { public void realRun() {
sync.acquire(); sync.acquire();
assertTrue(pleaseInterrupt.releaseShared(0)); assertTrue(pleaseInterrupt.releaseShared(0));
c.awaitUninterruptibly(); condition.awaitUninterruptibly();
assertTrue(Thread.interrupted()); assertTrue(Thread.interrupted());
assertHasWaitersLocked(sync, c, NO_THREADS); assertHasWaitersLocked(sync, condition, NO_THREADS);
sync.release(); sync.release();
}}); }});
pleaseInterrupt.acquireShared(0); pleaseInterrupt.acquireShared(0);
sync.acquire(); sync.acquire();
assertHasWaitersLocked(sync, c, t); assertHasWaitersLocked(sync, condition, t);
sync.release(); sync.release();
t.interrupt(); t.interrupt();
assertHasWaitersUnlocked(sync, c, t); assertHasWaitersUnlocked(sync, condition, t);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
sync.acquire(); sync.acquire();
assertHasWaitersLocked(sync, c, t); assertHasWaitersLocked(sync, condition, t);
assertHasExclusiveQueuedThreads(sync, NO_THREADS); assertHasExclusiveQueuedThreads(sync, NO_THREADS);
c.signal(); condition.signal();
assertHasWaitersLocked(sync, c, NO_THREADS); assertHasWaitersLocked(sync, condition, NO_THREADS);
assertHasExclusiveQueuedThreads(sync, t); assertHasExclusiveQueuedThreads(sync, t);
sync.release(); sync.release();
awaitTermination(t); awaitTermination(t);
@ -1161,7 +1162,7 @@ public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
waitForQueuedThread(l, t); waitForQueuedThread(l, t);
assertFalse(l.isSignalled()); assertFalse(l.isSignalled());
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
assertHasSharedQueuedThreads(l, t); assertHasSharedQueuedThreads(l, t);
assertTrue(l.releaseShared(0)); assertTrue(l.releaseShared(0));
assertTrue(l.isSignalled()); assertTrue(l.isSignalled());
@ -1186,7 +1187,7 @@ public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
waitForQueuedThread(l, t); waitForQueuedThread(l, t);
assertFalse(l.isSignalled()); assertFalse(l.isSignalled());
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
assertTrue(l.releaseShared(0)); assertTrue(l.releaseShared(0));
assertTrue(l.isSignalled()); assertTrue(l.isSignalled());
awaitTermination(t); awaitTermination(t);

View File

@ -130,7 +130,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
} }
/** /**
* Constructor throws IAE if capacity argument nonpositive * Constructor throws IllegalArgumentException if capacity argument nonpositive
*/ */
public void testConstructor_nonPositiveCapacity() { public void testConstructor_nonPositiveCapacity() {
for (int i : new int[] { 0, -1, Integer.MIN_VALUE }) { for (int i : new int[] { 0, -1, Integer.MIN_VALUE }) {
@ -183,7 +183,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
} }
/** /**
* Initializing from too large collection throws IAE * Initializing from too large collection throws IllegalArgumentException
*/ */
public void testConstructor_collectionTooLarge() { public void testConstructor_collectionTooLarge() {
// just barely fits - succeeds // just barely fits - succeeds
@ -254,7 +254,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
} }
/** /**
* add succeeds if not full; throws ISE if full * add succeeds if not full; throws IllegalStateException if full
*/ */
public void testAdd() { public void testAdd() {
ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE); ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
@ -267,7 +267,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
} }
/** /**
* addAll(this) throws IAE * addAll(this) throws IllegalArgumentException
*/ */
public void testAddAllSelf() { public void testAddAllSelf() {
ArrayBlockingQueue q = populatedQueue(SIZE); ArrayBlockingQueue q = populatedQueue(SIZE);
@ -293,7 +293,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
} }
/** /**
* addAll throws ISE if not enough room * addAll throws IllegalStateException if not enough room
*/ */
public void testAddAll_insufficientSpace() { public void testAddAll_insufficientSpace() {
int size = ThreadLocalRandom.current().nextInt(1, SIZE); int size = ThreadLocalRandom.current().nextInt(1, SIZE);
@ -367,7 +367,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
assertEquals(SIZE, q.size()); assertEquals(SIZE, q.size());
@ -389,6 +389,13 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
pleaseTake.countDown(); pleaseTake.countDown();
q.put(86); q.put(86);
Thread.currentThread().interrupt();
try {
q.put(99);
shouldThrow();
} catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
pleaseInterrupt.countDown(); pleaseInterrupt.countDown();
try { try {
q.put(99); q.put(99);
@ -402,7 +409,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
assertEquals(0, q.take()); assertEquals(0, q.take());
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
assertEquals(0, q.remainingCapacity()); assertEquals(0, q.remainingCapacity());
@ -411,7 +418,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
/** /**
* timed offer times out if full and elements not taken * timed offer times out if full and elements not taken
*/ */
public void testTimedOffer() throws InterruptedException { public void testTimedOffer() {
final ArrayBlockingQueue q = new ArrayBlockingQueue(2); final ArrayBlockingQueue q = new ArrayBlockingQueue(2);
final CountDownLatch pleaseInterrupt = new CountDownLatch(1); final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
@ -421,15 +428,24 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
long startTime = System.nanoTime(); long startTime = System.nanoTime();
assertFalse(q.offer(new Object(), timeoutMillis(), MILLISECONDS)); assertFalse(q.offer(new Object(), timeoutMillis(), MILLISECONDS));
assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
Thread.currentThread().interrupt();
try {
q.offer(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS);
shouldThrow();
} catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
pleaseInterrupt.countDown(); pleaseInterrupt.countDown();
try { try {
q.offer(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS); q.offer(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS);
shouldThrow(); shouldThrow();
} catch (InterruptedException success) {} } catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -452,9 +468,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
final CountDownLatch pleaseInterrupt = new CountDownLatch(1); final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException { public void realRun() throws InterruptedException {
for (int i = 0; i < SIZE; ++i) { for (int i = 0; i < SIZE; i++) assertEquals(i, q.take());
assertEquals(i, q.take());
}
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
try { try {
@ -472,7 +486,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -522,24 +536,32 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
*/ */
public void testInterruptedTimedPoll() throws InterruptedException { public void testInterruptedTimedPoll() throws InterruptedException {
final BlockingQueue<Integer> q = populatedQueue(SIZE); final BlockingQueue<Integer> q = populatedQueue(SIZE);
final CountDownLatch aboutToWait = new CountDownLatch(1); final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException { public void realRun() throws InterruptedException {
long startTime = System.nanoTime(); long startTime = System.nanoTime();
for (int i = 0; i < SIZE; ++i) { for (int i = 0; i < SIZE; i++)
assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS)); assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS));
}
aboutToWait.countDown(); Thread.currentThread().interrupt();
try { try {
q.poll(LONG_DELAY_MS, MILLISECONDS); q.poll(LONG_DELAY_MS, MILLISECONDS);
shouldThrow(); shouldThrow();
} catch (InterruptedException success) { } catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
pleaseInterrupt.countDown();
try {
q.poll(LONG_DELAY_MS, MILLISECONDS);
shouldThrow();
} catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
}
}}); }});
await(aboutToWait); await(pleaseInterrupt);
waitForThreadToEnterWaitState(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
checkEmpty(q); checkEmpty(q);

View File

@ -133,7 +133,7 @@ public abstract class BlockingQueueTest extends JSR166TestCase {
} }
/** /**
* put(null) throws NullPointerException * addAll(null) throws NullPointerException
*/ */
public void testAddAllNull() throws InterruptedException { public void testAddAllNull() throws InterruptedException {
final Collection q = emptyCollection(); final Collection q = emptyCollection();
@ -272,7 +272,7 @@ public abstract class BlockingQueueTest extends JSR166TestCase {
assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
barrier.await(); barrier.await();
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -294,7 +294,7 @@ public abstract class BlockingQueueTest extends JSR166TestCase {
}}); }});
await(threadStarted); await(threadStarted);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -335,7 +335,7 @@ public abstract class BlockingQueueTest extends JSR166TestCase {
}}); }});
await(threadStarted); await(threadStarted);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }

View File

@ -167,12 +167,12 @@ public class Collection8Test extends JSR166TestCase {
} }
if (c instanceof BlockingQueue) { if (c instanceof BlockingQueue) {
BlockingQueue q = (BlockingQueue) c; BlockingQueue q = (BlockingQueue) c;
assertNull(q.poll(0L, MILLISECONDS)); assertNull(q.poll(randomExpiredTimeout(), randomTimeUnit()));
} }
if (c instanceof BlockingDeque) { if (c instanceof BlockingDeque) {
BlockingDeque q = (BlockingDeque) c; BlockingDeque q = (BlockingDeque) c;
assertNull(q.pollFirst(0L, MILLISECONDS)); assertNull(q.pollFirst(randomExpiredTimeout(), randomTimeUnit()));
assertNull(q.pollLast(0L, MILLISECONDS)); assertNull(q.pollLast(randomExpiredTimeout(), randomTimeUnit()));
} }
} }

View File

@ -91,7 +91,7 @@ public class CompletableFutureTest extends JSR166TestCase {
assertNull(f.getNow(null)); assertNull(f.getNow(null));
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
try { try {
f.get(0L, SECONDS); f.get(randomExpiredTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} }
catch (TimeoutException success) {} catch (TimeoutException success) {}
@ -103,11 +103,7 @@ public class CompletableFutureTest extends JSR166TestCase {
try { try {
assertEquals(value, f.join()); assertEquals(value, f.join());
} catch (Throwable fail) { threadUnexpectedException(fail); }
try {
assertEquals(value, f.getNow(null)); assertEquals(value, f.getNow(null));
} catch (Throwable fail) { threadUnexpectedException(fail); }
try {
assertEquals(value, f.get()); assertEquals(value, f.get());
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
assertTrue(f.isDone()); assertTrue(f.isDone());
@ -1269,6 +1265,7 @@ public class CompletableFutureTest extends JSR166TestCase {
r.assertInvoked(); r.assertInvoked();
}} }}
@SuppressWarnings("FutureReturnValueIgnored")
public void testRunAsync_rejectingExecutor() { public void testRunAsync_rejectingExecutor() {
CountingRejectingExecutor e = new CountingRejectingExecutor(); CountingRejectingExecutor e = new CountingRejectingExecutor();
try { try {
@ -1315,6 +1312,7 @@ public class CompletableFutureTest extends JSR166TestCase {
r.assertInvoked(); r.assertInvoked();
}} }}
@SuppressWarnings("FutureReturnValueIgnored")
public void testSupplyAsync_rejectingExecutor() { public void testSupplyAsync_rejectingExecutor() {
CountingRejectingExecutor e = new CountingRejectingExecutor(); CountingRejectingExecutor e = new CountingRejectingExecutor();
try { try {
@ -3265,6 +3263,7 @@ public class CompletableFutureTest extends JSR166TestCase {
/** /**
* Completion methods throw NullPointerException with null arguments * Completion methods throw NullPointerException with null arguments
*/ */
@SuppressWarnings("FutureReturnValueIgnored")
public void testNPE() { public void testNPE() {
CompletableFuture<Integer> f = new CompletableFuture<>(); CompletableFuture<Integer> f = new CompletableFuture<>();
CompletableFuture<Integer> g = new CompletableFuture<>(); CompletableFuture<Integer> g = new CompletableFuture<>();
@ -4326,6 +4325,7 @@ public class CompletableFutureTest extends JSR166TestCase {
} }
/** Test long recursive chains of CompletableFutures with cascading completions */ /** Test long recursive chains of CompletableFutures with cascading completions */
@SuppressWarnings("FutureReturnValueIgnored")
public void testRecursiveChains() throws Throwable { public void testRecursiveChains() throws Throwable {
for (ExecutionMode m : ExecutionMode.values()) for (ExecutionMode m : ExecutionMode.values())
for (boolean addDeadEnds : new boolean[] { true, false }) for (boolean addDeadEnds : new boolean[] { true, false })
@ -4350,6 +4350,7 @@ public class CompletableFutureTest extends JSR166TestCase {
* A single CompletableFuture with many dependents. * A single CompletableFuture with many dependents.
* A demo of scalability - runtime is O(n). * A demo of scalability - runtime is O(n).
*/ */
@SuppressWarnings("FutureReturnValueIgnored")
public void testManyDependents() throws Throwable { public void testManyDependents() throws Throwable {
final int n = expensiveTests ? 1_000_000 : 10; final int n = expensiveTests ? 1_000_000 : 10;
final CompletableFuture<Void> head = new CompletableFuture<>(); final CompletableFuture<Void> head = new CompletableFuture<>();
@ -4379,6 +4380,7 @@ public class CompletableFutureTest extends JSR166TestCase {
} }
/** ant -Dvmoptions=-Xmx8m -Djsr166.expensiveTests=true -Djsr166.tckTestClass=CompletableFutureTest tck */ /** ant -Dvmoptions=-Xmx8m -Djsr166.expensiveTests=true -Djsr166.tckTestClass=CompletableFutureTest tck */
@SuppressWarnings("FutureReturnValueIgnored")
public void testCoCompletionGarbageRetention() throws Throwable { public void testCoCompletionGarbageRetention() throws Throwable {
final int n = expensiveTests ? 1_000_000 : 10; final int n = expensiveTests ? 1_000_000 : 10;
final CompletableFuture<Integer> incomplete = new CompletableFuture<>(); final CompletableFuture<Integer> incomplete = new CompletableFuture<>();

View File

@ -339,7 +339,7 @@ public class ConcurrentLinkedDequeTest extends JSR166TestCase {
} }
/** /**
* addAll(this) throws IAE * addAll(this) throws IllegalArgumentException
*/ */
public void testAddAllSelf() { public void testAddAllSelf() {
ConcurrentLinkedDeque q = populatedDeque(SIZE); ConcurrentLinkedDeque q = populatedDeque(SIZE);

View File

@ -199,7 +199,7 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
} }
/** /**
* addAll(null) throws NPE * addAll(null) throws NullPointerException
*/ */
public void testAddAll1() { public void testAddAll1() {
ConcurrentLinkedQueue q = new ConcurrentLinkedQueue(); ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
@ -210,7 +210,7 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
} }
/** /**
* addAll(this) throws IAE * addAll(this) throws IllegalArgumentException
*/ */
public void testAddAllSelf() { public void testAddAllSelf() {
ConcurrentLinkedQueue q = populatedQueue(SIZE); ConcurrentLinkedQueue q = populatedQueue(SIZE);
@ -221,7 +221,7 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
} }
/** /**
* addAll of a collection with null elements throws NPE * addAll of a collection with null elements throws NullPointerException
*/ */
public void testAddAll2() { public void testAddAll2() {
ConcurrentLinkedQueue q = new ConcurrentLinkedQueue(); ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();

View File

@ -49,7 +49,7 @@ public class CountDownLatchTest extends JSR166TestCase {
} }
/** /**
* negative constructor argument throws IAE * negative constructor argument throws IllegalArgumentException
*/ */
public void testConstructor() { public void testConstructor() {
try { try {
@ -99,7 +99,7 @@ public class CountDownLatchTest extends JSR166TestCase {
assertEquals(2, l.getCount()); assertEquals(2, l.getCount());
l.countDown(); l.countDown();
assertEquals(1, l.getCount()); assertEquals(1, l.getCount());
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
l.countDown(); l.countDown();
assertEquals(0, l.getCount()); assertEquals(0, l.getCount());
awaitTermination(t); awaitTermination(t);
@ -124,14 +124,14 @@ public class CountDownLatchTest extends JSR166TestCase {
assertEquals(2, l.getCount()); assertEquals(2, l.getCount());
l.countDown(); l.countDown();
assertEquals(1, l.getCount()); assertEquals(1, l.getCount());
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
l.countDown(); l.countDown();
assertEquals(0, l.getCount()); assertEquals(0, l.getCount());
awaitTermination(t); awaitTermination(t);
} }
/** /**
* await throws IE if interrupted before counted down * await throws InterruptedException if interrupted before counted down
*/ */
public void testAwait_Interruptible() { public void testAwait_Interruptible() {
final CountDownLatch l = new CountDownLatch(1); final CountDownLatch l = new CountDownLatch(1);
@ -156,13 +156,13 @@ public class CountDownLatchTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
/** /**
* timed await throws IE if interrupted before counted down * timed await throws InterruptedException if interrupted before counted down
*/ */
public void testTimedAwait_Interruptible() { public void testTimedAwait_Interruptible() {
final CountDownLatch l = new CountDownLatch(1); final CountDownLatch l = new CountDownLatch(1);
@ -187,7 +187,7 @@ public class CountDownLatchTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }

View File

@ -32,7 +32,6 @@
*/ */
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.HashSet; import java.util.HashSet;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
@ -104,7 +103,7 @@ public class CountedCompleterTest extends JSR166TestCase {
assertNull(a.getRawResult()); assertNull(a.getRawResult());
try { try {
a.get(0L, SECONDS); a.get(randomExpiredTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (TimeoutException success) { } catch (TimeoutException success) {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
@ -122,7 +121,7 @@ public class CountedCompleterTest extends JSR166TestCase {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
long startTime = System.nanoTime(); long startTime = System.nanoTime();
assertNull(a.join()); assertNull(a.join());
assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
Thread.interrupted(); Thread.interrupted();
} }
@ -130,7 +129,7 @@ public class CountedCompleterTest extends JSR166TestCase {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
long startTime = System.nanoTime(); long startTime = System.nanoTime();
a.quietlyJoin(); // should be no-op a.quietlyJoin(); // should be no-op
assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
Thread.interrupted(); Thread.interrupted();
} }
@ -138,9 +137,7 @@ public class CountedCompleterTest extends JSR166TestCase {
assertFalse(a.cancel(true)); assertFalse(a.cancel(true));
try { try {
assertNull(a.get()); assertNull(a.get());
} catch (Throwable fail) { threadUnexpectedException(fail); } assertNull(a.get(randomTimeout(), randomTimeUnit()));
try {
assertNull(a.get(5L, SECONDS));
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
} }
@ -165,7 +162,7 @@ public class CountedCompleterTest extends JSR166TestCase {
{ {
long startTime = System.nanoTime(); long startTime = System.nanoTime();
a.quietlyJoin(); // should be no-op a.quietlyJoin(); // should be no-op
assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
} }
try { try {
@ -175,7 +172,7 @@ public class CountedCompleterTest extends JSR166TestCase {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
try { try {
a.get(5L, SECONDS); a.get(randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (CancellationException success) { } catch (CancellationException success) {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
@ -203,7 +200,7 @@ public class CountedCompleterTest extends JSR166TestCase {
{ {
long startTime = System.nanoTime(); long startTime = System.nanoTime();
a.quietlyJoin(); // should be no-op a.quietlyJoin(); // should be no-op
assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
} }
try { try {
@ -214,7 +211,7 @@ public class CountedCompleterTest extends JSR166TestCase {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
try { try {
a.get(5L, SECONDS); a.get(randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (ExecutionException success) { } catch (ExecutionException success) {
assertSame(t.getClass(), success.getCause().getClass()); assertSame(t.getClass(), success.getCause().getClass());
@ -729,7 +726,7 @@ public class CountedCompleterTest extends JSR166TestCase {
CCF f = new LCCF(8); CCF f = new LCCF(8);
assertSame(f, f.fork()); assertSame(f, f.fork());
try { try {
f.get(5L, null); f.get(randomTimeout(), null);
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
}}; }};
@ -1451,7 +1448,7 @@ public class CountedCompleterTest extends JSR166TestCase {
CCF f = new LCCF(8); CCF f = new LCCF(8);
assertSame(f, f.fork()); assertSame(f, f.fork());
try { try {
f.get(5L, null); f.get(randomTimeout(), null);
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
}}; }};

View File

@ -66,7 +66,7 @@ public class CyclicBarrierTest extends JSR166TestCase {
} }
/** /**
* Creating with negative parties throws IAE * Creating with negative parties throws IllegalArgumentException
*/ */
public void testConstructor1() { public void testConstructor1() {
try { try {
@ -76,7 +76,8 @@ public class CyclicBarrierTest extends JSR166TestCase {
} }
/** /**
* Creating with negative parties and no action throws IAE * Creating with negative parties and no action throws
* IllegalArgumentException
*/ */
public void testConstructor2() { public void testConstructor2() {
try { try {

View File

@ -142,7 +142,7 @@ public class DelayQueueTest extends JSR166TestCase {
* Returns a new queue of given size containing consecutive * Returns a new queue of given size containing consecutive
* PDelays 0 ... n - 1. * PDelays 0 ... n - 1.
*/ */
private DelayQueue<PDelay> populatedQueue(int n) { private static DelayQueue<PDelay> populatedQueue(int n) {
DelayQueue<PDelay> q = new DelayQueue<>(); DelayQueue<PDelay> q = new DelayQueue<>();
assertTrue(q.isEmpty()); assertTrue(q.isEmpty());
for (int i = n - 1; i >= 0; i -= 2) for (int i = n - 1; i >= 0; i -= 2)
@ -261,7 +261,7 @@ public class DelayQueueTest extends JSR166TestCase {
} }
/** /**
* addAll(this) throws IAE * addAll(this) throws IllegalArgumentException
*/ */
public void testAddAllSelf() { public void testAddAllSelf() {
DelayQueue q = populatedQueue(SIZE); DelayQueue q = populatedQueue(SIZE);
@ -365,9 +365,8 @@ public class DelayQueueTest extends JSR166TestCase {
final CountDownLatch pleaseInterrupt = new CountDownLatch(1); final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException { public void realRun() throws InterruptedException {
for (int i = 0; i < SIZE; ++i) { for (int i = 0; i < SIZE; i++)
assertEquals(new PDelay(i), ((PDelay)q.take())); assertEquals(new PDelay(i), ((PDelay)q.take()));
}
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
try { try {
@ -385,7 +384,7 @@ public class DelayQueueTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -438,10 +437,9 @@ public class DelayQueueTest extends JSR166TestCase {
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException { public void realRun() throws InterruptedException {
long startTime = System.nanoTime(); long startTime = System.nanoTime();
for (int i = 0; i < SIZE; ++i) { for (int i = 0; i < SIZE; i++)
assertEquals(new PDelay(i), assertEquals(new PDelay(i),
((PDelay)q.poll(LONG_DELAY_MS, MILLISECONDS))); ((PDelay)q.poll(LONG_DELAY_MS, MILLISECONDS)));
}
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
try { try {
@ -456,11 +454,12 @@ public class DelayQueueTest extends JSR166TestCase {
shouldThrow(); shouldThrow();
} catch (InterruptedException success) {} } catch (InterruptedException success) {}
assertFalse(Thread.interrupted()); assertFalse(Thread.interrupted());
assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
checkEmpty(q); checkEmpty(q);
@ -741,7 +740,9 @@ public class DelayQueueTest extends JSR166TestCase {
public void testTimedPollDelayed() throws InterruptedException { public void testTimedPollDelayed() throws InterruptedException {
DelayQueue q = new DelayQueue(); DelayQueue q = new DelayQueue();
q.add(new NanoDelay(LONG_DELAY_MS * 1000000L)); q.add(new NanoDelay(LONG_DELAY_MS * 1000000L));
long startTime = System.nanoTime();
assertNull(q.poll(timeoutMillis(), MILLISECONDS)); assertNull(q.poll(timeoutMillis(), MILLISECONDS));
assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
} }
/** /**

View File

@ -34,6 +34,7 @@
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Phaser; import java.util.concurrent.Phaser;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.DoubleAccumulator; import java.util.concurrent.atomic.DoubleAccumulator;
import junit.framework.Test; import junit.framework.Test;
@ -48,135 +49,130 @@ public class DoubleAccumulatorTest extends JSR166TestCase {
} }
/** /**
* default constructed initializes to zero * new instance initialized to supplied identity
*/ */
public void testConstructor() { public void testConstructor() {
DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0); for (double identity : new double[] {
assertEquals(0.0, ai.get()); Double.NEGATIVE_INFINITY,
Double.POSITIVE_INFINITY,
Double.MIN_VALUE,
Double.MAX_VALUE,
0.0,
})
assertEquals(identity,
new DoubleAccumulator(Double::max, identity).get());
} }
/** /**
* accumulate accumulates given value to current, and get returns current value * accumulate accumulates given value to current, and get returns current value
*/ */
public void testAccumulateAndGet() { public void testAccumulateAndGet() {
DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0); DoubleAccumulator acc = new DoubleAccumulator(Double::max, 0.0);
ai.accumulate(2.0); acc.accumulate(2.0);
assertEquals(2.0, ai.get()); assertEquals(2.0, acc.get());
ai.accumulate(-4.0); acc.accumulate(-4.0);
assertEquals(2.0, ai.get()); assertEquals(2.0, acc.get());
ai.accumulate(4.0); acc.accumulate(4.0);
assertEquals(4.0, ai.get()); assertEquals(4.0, acc.get());
} }
/** /**
* reset() causes subsequent get() to return zero * reset() causes subsequent get() to return zero
*/ */
public void testReset() { public void testReset() {
DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0); DoubleAccumulator acc = new DoubleAccumulator(Double::max, 0.0);
ai.accumulate(2.0); acc.accumulate(2.0);
assertEquals(2.0, ai.get()); assertEquals(2.0, acc.get());
ai.reset(); acc.reset();
assertEquals(0.0, ai.get()); assertEquals(0.0, acc.get());
} }
/** /**
* getThenReset() returns current value; subsequent get() returns zero * getThenReset() returns current value; subsequent get() returns zero
*/ */
public void testGetThenReset() { public void testGetThenReset() {
DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0); DoubleAccumulator acc = new DoubleAccumulator(Double::max, 0.0);
ai.accumulate(2.0); acc.accumulate(2.0);
assertEquals(2.0, ai.get()); assertEquals(2.0, acc.get());
assertEquals(2.0, ai.getThenReset()); assertEquals(2.0, acc.getThenReset());
assertEquals(0.0, ai.get()); assertEquals(0.0, acc.get());
} }
/** /**
* toString returns current value. * toString returns current value.
*/ */
public void testToString() { public void testToString() {
DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0); DoubleAccumulator acc = new DoubleAccumulator(Double::max, 0.0);
assertEquals("0.0", ai.toString()); assertEquals("0.0", acc.toString());
ai.accumulate(1.0); acc.accumulate(1.0);
assertEquals(Double.toString(1.0), ai.toString()); assertEquals(Double.toString(1.0), acc.toString());
} }
/** /**
* intValue returns current value. * intValue returns current value.
*/ */
public void testIntValue() { public void testIntValue() {
DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0); DoubleAccumulator acc = new DoubleAccumulator(Double::max, 0.0);
assertEquals(0, ai.intValue()); assertEquals(0, acc.intValue());
ai.accumulate(1.0); acc.accumulate(1.0);
assertEquals(1, ai.intValue()); assertEquals(1, acc.intValue());
} }
/** /**
* longValue returns current value. * longValue returns current value.
*/ */
public void testLongValue() { public void testLongValue() {
DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0); DoubleAccumulator acc = new DoubleAccumulator(Double::max, 0.0);
assertEquals(0, ai.longValue()); assertEquals(0, acc.longValue());
ai.accumulate(1.0); acc.accumulate(1.0);
assertEquals(1, ai.longValue()); assertEquals(1, acc.longValue());
} }
/** /**
* floatValue returns current value. * floatValue returns current value.
*/ */
public void testFloatValue() { public void testFloatValue() {
DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0); DoubleAccumulator acc = new DoubleAccumulator(Double::max, 0.0);
assertEquals(0.0f, ai.floatValue()); assertEquals(0.0f, acc.floatValue());
ai.accumulate(1.0); acc.accumulate(1.0);
assertEquals(1.0f, ai.floatValue()); assertEquals(1.0f, acc.floatValue());
} }
/** /**
* doubleValue returns current value. * doubleValue returns current value.
*/ */
public void testDoubleValue() { public void testDoubleValue() {
DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0); DoubleAccumulator acc = new DoubleAccumulator(Double::max, 0.0);
assertEquals(0.0, ai.doubleValue()); assertEquals(0.0, acc.doubleValue());
ai.accumulate(1.0); acc.accumulate(1.0);
assertEquals(1.0, ai.doubleValue()); assertEquals(1.0, acc.doubleValue());
} }
/** /**
* accumulates by multiple threads produce correct result * accumulates by multiple threads produce correct result
*/ */
public void testAccumulateAndGetMT() { public void testAccumulateAndGetMT() {
final int incs = 1000000; final DoubleAccumulator acc
final int nthreads = 4; = new DoubleAccumulator((x, y) -> x + y, 0.0);
final ExecutorService pool = Executors.newCachedThreadPool(); final int nThreads = ThreadLocalRandom.current().nextInt(1, 5);
DoubleAccumulator a = new DoubleAccumulator(Double::max, 0.0); final Phaser phaser = new Phaser(nThreads + 1);
Phaser phaser = new Phaser(nthreads + 1); final int incs = 1_000_000;
for (int i = 0; i < nthreads; ++i) final double total = nThreads * incs/2.0 * (incs - 1); // Gauss
pool.execute(new AccTask(a, phaser, incs)); final Runnable task = () -> {
phaser.arriveAndAwaitAdvance(); phaser.arriveAndAwaitAdvance();
phaser.arriveAndAwaitAdvance(); for (int i = 0; i < incs; i++) {
double expected = incs - 1; acc.accumulate((double) i);
double result = a.get(); assertTrue(acc.get() <= total);
assertEquals(expected, result);
pool.shutdown();
} }
static final class AccTask implements Runnable {
final DoubleAccumulator acc;
final Phaser phaser;
final int incs;
volatile double result;
AccTask(DoubleAccumulator acc, Phaser phaser, int incs) {
this.acc = acc;
this.phaser = phaser;
this.incs = incs;
}
public void run() {
phaser.arriveAndAwaitAdvance();
DoubleAccumulator a = acc;
for (int i = 0; i < incs; ++i)
a.accumulate(i);
result = a.get();
phaser.arrive(); phaser.arrive();
};
final ExecutorService p = Executors.newCachedThreadPool();
try (PoolCleaner cleaner = cleaner(p)) {
for (int i = nThreads; i-->0; )
p.execute(task);
phaser.arriveAndAwaitAdvance();
phaser.arriveAndAwaitAdvance();
assertEquals(total, acc.get());
} }
} }

View File

@ -92,7 +92,7 @@ public class ExchangerTest extends JSR166TestCase {
} }
/** /**
* interrupt during wait for exchange throws IE * interrupt during wait for exchange throws InterruptedException
*/ */
public void testExchange_InterruptedException() { public void testExchange_InterruptedException() {
final Exchanger e = new Exchanger(); final Exchanger e = new Exchanger();
@ -109,7 +109,7 @@ public class ExchangerTest extends JSR166TestCase {
} }
/** /**
* interrupt during wait for timed exchange throws IE * interrupt during wait for timed exchange throws InterruptedException
*/ */
public void testTimedExchange_InterruptedException() { public void testTimedExchange_InterruptedException() {
final Exchanger e = new Exchanger(); final Exchanger e = new Exchanger();

View File

@ -167,7 +167,8 @@ public class ExecutorsTest extends JSR166TestCase {
} }
/** /**
* A new newFixedThreadPool with null ThreadFactory throws NPE * A new newFixedThreadPool with null ThreadFactory throws
* NullPointerException
*/ */
public void testNewFixedThreadPool3() { public void testNewFixedThreadPool3() {
try { try {
@ -177,7 +178,7 @@ public class ExecutorsTest extends JSR166TestCase {
} }
/** /**
* A new newFixedThreadPool with 0 threads throws IAE * A new newFixedThreadPool with 0 threads throws IllegalArgumentException
*/ */
public void testNewFixedThreadPool4() { public void testNewFixedThreadPool4() {
try { try {

View File

@ -32,7 +32,6 @@
*/ */
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.HashSet; import java.util.HashSet;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
@ -111,14 +110,14 @@ public class ForkJoinPool8Test extends JSR166TestCase {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
try { try {
a.get(5L, SECONDS); a.get(randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (InterruptedException success) { } catch (InterruptedException success) {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
} }
try { try {
a.get(0L, SECONDS); a.get(randomExpiredTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (TimeoutException success) { } catch (TimeoutException success) {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
@ -136,9 +135,7 @@ public class ForkJoinPool8Test extends JSR166TestCase {
assertFalse(a.cancel(true)); assertFalse(a.cancel(true));
try { try {
assertNull(a.get()); assertNull(a.get());
} catch (Throwable fail) { threadUnexpectedException(fail); } assertNull(a.get(randomTimeout(), randomTimeUnit()));
try {
assertNull(a.get(5L, SECONDS));
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
} }
@ -163,7 +160,7 @@ public class ForkJoinPool8Test extends JSR166TestCase {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
try { try {
a.get(5L, SECONDS); a.get(randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (CancellationException success) { } catch (CancellationException success) {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
@ -194,7 +191,7 @@ public class ForkJoinPool8Test extends JSR166TestCase {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
try { try {
a.get(5L, SECONDS); a.get(randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (ExecutionException success) { } catch (ExecutionException success) {
assertSame(t.getClass(), success.getCause().getClass()); assertSame(t.getClass(), success.getCause().getClass());
@ -383,7 +380,7 @@ public class ForkJoinPool8Test extends JSR166TestCase {
protected void realCompute() throws Exception { protected void realCompute() throws Exception {
FibAction f = new FibAction(8); FibAction f = new FibAction(8);
assertSame(f, f.fork()); assertSame(f, f.fork());
assertNull(f.get(5L, SECONDS)); assertNull(f.get(LONG_DELAY_MS, MILLISECONDS));
assertEquals(21, f.result); assertEquals(21, f.result);
checkCompletedNormally(f); checkCompletedNormally(f);
}}; }};
@ -399,7 +396,7 @@ public class ForkJoinPool8Test extends JSR166TestCase {
FibAction f = new FibAction(8); FibAction f = new FibAction(8);
assertSame(f, f.fork()); assertSame(f, f.fork());
try { try {
f.get(5L, null); f.get(randomTimeout(), null);
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
}}; }};
@ -499,7 +496,7 @@ public class ForkJoinPool8Test extends JSR166TestCase {
FailingFibAction f = new FailingFibAction(8); FailingFibAction f = new FailingFibAction(8);
assertSame(f, f.fork()); assertSame(f, f.fork());
try { try {
f.get(5L, SECONDS); f.get(LONG_DELAY_MS, MILLISECONDS);
shouldThrow(); shouldThrow();
} catch (ExecutionException success) { } catch (ExecutionException success) {
Throwable cause = success.getCause(); Throwable cause = success.getCause();
@ -591,7 +588,7 @@ public class ForkJoinPool8Test extends JSR166TestCase {
assertTrue(f.cancel(true)); assertTrue(f.cancel(true));
assertSame(f, f.fork()); assertSame(f, f.fork());
try { try {
f.get(5L, SECONDS); f.get(LONG_DELAY_MS, MILLISECONDS);
shouldThrow(); shouldThrow();
} catch (CancellationException success) { } catch (CancellationException success) {
checkCancelled(f); checkCancelled(f);
@ -1067,7 +1064,7 @@ public class ForkJoinPool8Test extends JSR166TestCase {
CCF f = new LCCF(null, 8); CCF f = new LCCF(null, 8);
assertSame(f, f.fork()); assertSame(f, f.fork());
try { try {
f.get(5L, null); f.get(randomTimeout(), null);
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
}}; }};

View File

@ -38,6 +38,7 @@ import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
@ -267,8 +268,8 @@ public class ForkJoinPoolTest extends JSR166TestCase {
assertFalse(p.awaitTermination(Long.MIN_VALUE, MILLISECONDS)); assertFalse(p.awaitTermination(Long.MIN_VALUE, MILLISECONDS));
assertFalse(p.awaitTermination(-1L, NANOSECONDS)); assertFalse(p.awaitTermination(-1L, NANOSECONDS));
assertFalse(p.awaitTermination(-1L, MILLISECONDS)); assertFalse(p.awaitTermination(-1L, MILLISECONDS));
assertFalse(p.awaitTermination(0L, NANOSECONDS)); assertFalse(p.awaitTermination(randomExpiredTimeout(),
assertFalse(p.awaitTermination(0L, MILLISECONDS)); randomTimeUnit()));
long timeoutNanos = 999999L; long timeoutNanos = 999999L;
long startTime = System.nanoTime(); long startTime = System.nanoTime();
assertFalse(p.awaitTermination(timeoutNanos, NANOSECONDS)); assertFalse(p.awaitTermination(timeoutNanos, NANOSECONDS));
@ -449,7 +450,7 @@ public class ForkJoinPoolTest extends JSR166TestCase {
done.set(true); done.set(true);
}}); }});
assertNull(future.get()); assertNull(future.get());
assertNull(future.get(0, MILLISECONDS)); assertNull(future.get(randomExpiredTimeout(), randomTimeUnit()));
assertTrue(done.get()); assertTrue(done.get());
assertTrue(future.isDone()); assertTrue(future.isDone());
assertFalse(future.isCancelled()); assertFalse(future.isCancelled());
@ -730,13 +731,14 @@ public class ForkJoinPoolTest extends JSR166TestCase {
} }
/** /**
* invokeAll(empty collection) returns empty collection * invokeAll(empty collection) returns empty list
*/ */
public void testInvokeAll2() throws InterruptedException { public void testInvokeAll2() throws InterruptedException {
ExecutorService e = new ForkJoinPool(1); ExecutorService e = new ForkJoinPool(1);
final Collection<Callable<String>> emptyCollection
= Collections.emptyList();
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
List<Future<String>> r List<Future<String>> r = e.invokeAll(emptyCollection);
= e.invokeAll(new ArrayList<Callable<String>>());
assertTrue(r.isEmpty()); assertTrue(r.isEmpty());
} }
} }
@ -800,7 +802,7 @@ public class ForkJoinPoolTest extends JSR166TestCase {
ExecutorService e = new ForkJoinPool(1); ExecutorService e = new ForkJoinPool(1);
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
try { try {
e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAny(null, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
@ -815,7 +817,7 @@ public class ForkJoinPoolTest extends JSR166TestCase {
List<Callable<String>> l = new ArrayList<>(); List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask()); l.add(new StringTask());
try { try {
e.invokeAny(l, MEDIUM_DELAY_MS, null); e.invokeAny(l, randomTimeout(), null);
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
@ -829,7 +831,7 @@ public class ForkJoinPoolTest extends JSR166TestCase {
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
try { try {
e.invokeAny(new ArrayList<Callable<String>>(), e.invokeAny(new ArrayList<Callable<String>>(),
MEDIUM_DELAY_MS, MILLISECONDS); randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (IllegalArgumentException success) {} } catch (IllegalArgumentException success) {}
} }
@ -846,7 +848,7 @@ public class ForkJoinPoolTest extends JSR166TestCase {
l.add(latchAwaitingStringTask(latch)); l.add(latchAwaitingStringTask(latch));
l.add(null); l.add(null);
try { try {
e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAny(l, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
latch.countDown(); latch.countDown();
@ -895,7 +897,7 @@ public class ForkJoinPoolTest extends JSR166TestCase {
ExecutorService e = new ForkJoinPool(1); ExecutorService e = new ForkJoinPool(1);
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
try { try {
e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAll(null, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
@ -910,21 +912,23 @@ public class ForkJoinPoolTest extends JSR166TestCase {
List<Callable<String>> l = new ArrayList<>(); List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask()); l.add(new StringTask());
try { try {
e.invokeAll(l, MEDIUM_DELAY_MS, null); e.invokeAll(l, randomTimeout(), null);
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
} }
/** /**
* timed invokeAll(empty collection) returns empty collection * timed invokeAll(empty collection) returns empty list
*/ */
public void testTimedInvokeAll2() throws InterruptedException { public void testTimedInvokeAll2() throws InterruptedException {
ExecutorService e = new ForkJoinPool(1); ExecutorService e = new ForkJoinPool(1);
final Collection<Callable<String>> emptyCollection
= Collections.emptyList();
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
List<Future<String>> r List<Future<String>> r
= e.invokeAll(new ArrayList<Callable<String>>(), = e.invokeAll(emptyCollection,
MEDIUM_DELAY_MS, MILLISECONDS); randomTimeout(), randomTimeUnit());
assertTrue(r.isEmpty()); assertTrue(r.isEmpty());
} }
} }
@ -939,7 +943,7 @@ public class ForkJoinPoolTest extends JSR166TestCase {
l.add(new StringTask()); l.add(new StringTask());
l.add(null); l.add(null);
try { try {
e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAll(l, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }

View File

@ -32,7 +32,6 @@
*/ */
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.Arrays; import java.util.Arrays;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
@ -131,7 +130,7 @@ public class ForkJoinTask8Test extends JSR166TestCase {
((BinaryAsyncAction)a).getForkJoinTaskTag()); ((BinaryAsyncAction)a).getForkJoinTaskTag());
try { try {
a.get(0L, SECONDS); a.get(randomExpiredTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (TimeoutException success) { } catch (TimeoutException success) {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
@ -156,7 +155,7 @@ public class ForkJoinTask8Test extends JSR166TestCase {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
long startTime = System.nanoTime(); long startTime = System.nanoTime();
assertSame(expected, a.join()); assertSame(expected, a.join());
assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
Thread.interrupted(); Thread.interrupted();
} }
@ -164,7 +163,7 @@ public class ForkJoinTask8Test extends JSR166TestCase {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
long startTime = System.nanoTime(); long startTime = System.nanoTime();
a.quietlyJoin(); // should be no-op a.quietlyJoin(); // should be no-op
assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
Thread.interrupted(); Thread.interrupted();
} }
@ -172,9 +171,7 @@ public class ForkJoinTask8Test extends JSR166TestCase {
assertFalse(a.cancel(true)); assertFalse(a.cancel(true));
try { try {
assertSame(expected, a.get()); assertSame(expected, a.get());
} catch (Throwable fail) { threadUnexpectedException(fail); } assertSame(expected, a.get(randomTimeout(), randomTimeUnit()));
try {
assertSame(expected, a.get(5L, SECONDS));
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
} }
@ -202,7 +199,7 @@ public class ForkJoinTask8Test extends JSR166TestCase {
{ {
long startTime = System.nanoTime(); long startTime = System.nanoTime();
a.quietlyJoin(); // should be no-op a.quietlyJoin(); // should be no-op
assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
} }
try { try {
@ -213,7 +210,7 @@ public class ForkJoinTask8Test extends JSR166TestCase {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
try { try {
a.get(5L, SECONDS); a.get(randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (ExecutionException success) { } catch (ExecutionException success) {
assertSame(t.getClass(), success.getCause().getClass()); assertSame(t.getClass(), success.getCause().getClass());
@ -515,7 +512,7 @@ public class ForkJoinTask8Test extends JSR166TestCase {
AsyncFib f = new AsyncFib(8); AsyncFib f = new AsyncFib(8);
assertSame(f, f.fork()); assertSame(f, f.fork());
try { try {
f.get(5L, null); f.get(randomTimeout(), null);
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
}}; }};

View File

@ -32,7 +32,6 @@
*/ */
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
@ -104,7 +103,7 @@ public class ForkJoinTaskTest extends JSR166TestCase {
assertNull(a.getRawResult()); assertNull(a.getRawResult());
try { try {
a.get(0L, SECONDS); a.get(randomExpiredTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (TimeoutException success) { } catch (TimeoutException success) {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
@ -126,7 +125,7 @@ public class ForkJoinTaskTest extends JSR166TestCase {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
long startTime = System.nanoTime(); long startTime = System.nanoTime();
assertSame(expected, a.join()); assertSame(expected, a.join());
assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
Thread.interrupted(); Thread.interrupted();
} }
@ -134,7 +133,7 @@ public class ForkJoinTaskTest extends JSR166TestCase {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
long startTime = System.nanoTime(); long startTime = System.nanoTime();
a.quietlyJoin(); // should be no-op a.quietlyJoin(); // should be no-op
assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
Thread.interrupted(); Thread.interrupted();
} }
@ -142,9 +141,7 @@ public class ForkJoinTaskTest extends JSR166TestCase {
assertFalse(a.cancel(true)); assertFalse(a.cancel(true));
try { try {
assertSame(expected, a.get()); assertSame(expected, a.get());
} catch (Throwable fail) { threadUnexpectedException(fail); } assertSame(expected, a.get(randomTimeout(), randomTimeUnit()));
try {
assertSame(expected, a.get(5L, SECONDS));
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
} }
@ -169,7 +166,7 @@ public class ForkJoinTaskTest extends JSR166TestCase {
{ {
long startTime = System.nanoTime(); long startTime = System.nanoTime();
a.quietlyJoin(); // should be no-op a.quietlyJoin(); // should be no-op
assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
} }
try { try {
@ -179,7 +176,7 @@ public class ForkJoinTaskTest extends JSR166TestCase {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
try { try {
a.get(5L, SECONDS); a.get(randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (CancellationException success) { } catch (CancellationException success) {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
@ -207,7 +204,7 @@ public class ForkJoinTaskTest extends JSR166TestCase {
{ {
long startTime = System.nanoTime(); long startTime = System.nanoTime();
a.quietlyJoin(); // should be no-op a.quietlyJoin(); // should be no-op
assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
} }
try { try {
@ -218,7 +215,7 @@ public class ForkJoinTaskTest extends JSR166TestCase {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
try { try {
a.get(5L, SECONDS); a.get(randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (ExecutionException success) { } catch (ExecutionException success) {
assertSame(t.getClass(), success.getCause().getClass()); assertSame(t.getClass(), success.getCause().getClass());
@ -492,7 +489,7 @@ public class ForkJoinTaskTest extends JSR166TestCase {
AsyncFib f = new AsyncFib(8); AsyncFib f = new AsyncFib(8);
assertSame(f, f.fork()); assertSame(f, f.fork());
try { try {
f.get(5L, null); f.get(randomTimeout(), null);
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
}}; }};
@ -1239,7 +1236,7 @@ public class ForkJoinTaskTest extends JSR166TestCase {
AsyncFib f = new AsyncFib(8); AsyncFib f = new AsyncFib(8);
assertSame(f, f.fork()); assertSame(f, f.fork());
try { try {
f.get(5L, null); f.get(randomTimeout(), null);
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
}}; }};

View File

@ -35,7 +35,6 @@
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -135,9 +134,7 @@ public class FutureTaskTest extends JSR166TestCase {
try { try {
assertSame(expected, f.get()); assertSame(expected, f.get());
} catch (Throwable fail) { threadUnexpectedException(fail); } assertSame(expected, f.get(randomTimeout(), randomTimeUnit()));
try {
assertSame(expected, f.get(5L, SECONDS));
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
} }
@ -152,7 +149,7 @@ public class FutureTaskTest extends JSR166TestCase {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
try { try {
f.get(5L, SECONDS); f.get(randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (CancellationException success) { } catch (CancellationException success) {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
@ -178,7 +175,7 @@ public class FutureTaskTest extends JSR166TestCase {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
try { try {
f.get(5L, SECONDS); f.get(randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (ExecutionException success) { } catch (ExecutionException success) {
assertSame(t, success.getCause()); assertSame(t, success.getCause());
@ -444,6 +441,7 @@ public class FutureTaskTest extends JSR166TestCase {
delay(LONG_DELAY_MS); delay(LONG_DELAY_MS);
shouldThrow(); shouldThrow();
} catch (InterruptedException success) {} } catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
}}); }});
Thread t = newStartedThread(task); Thread t = newStartedThread(task);

View File

@ -103,18 +103,24 @@ import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier; import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.RecursiveAction; import java.util.concurrent.RecursiveAction;
import java.util.concurrent.RecursiveTask; import java.util.concurrent.RecursiveTask;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.Semaphore; import java.util.concurrent.Semaphore;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.SynchronousQueue; import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@ -665,6 +671,33 @@ public class JSR166TestCase extends TestCase {
public static long MEDIUM_DELAY_MS; public static long MEDIUM_DELAY_MS;
public static long LONG_DELAY_MS; public static long LONG_DELAY_MS;
private static final long RANDOM_TIMEOUT;
private static final long RANDOM_EXPIRED_TIMEOUT;
private static final TimeUnit RANDOM_TIMEUNIT;
static {
ThreadLocalRandom rnd = ThreadLocalRandom.current();
long[] timeouts = { Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE };
RANDOM_TIMEOUT = timeouts[rnd.nextInt(timeouts.length)];
RANDOM_EXPIRED_TIMEOUT = timeouts[rnd.nextInt(3)];
TimeUnit[] timeUnits = TimeUnit.values();
RANDOM_TIMEUNIT = timeUnits[rnd.nextInt(timeUnits.length)];
}
/**
* Returns a timeout for use when any value at all will do.
*/
static long randomTimeout() { return RANDOM_TIMEOUT; }
/**
* Returns a timeout that means "no waiting", i.e. not positive.
*/
static long randomExpiredTimeout() { return RANDOM_EXPIRED_TIMEOUT; }
/**
* Returns a random non-null TimeUnit.
*/
static TimeUnit randomTimeUnit() { return RANDOM_TIMEUNIT; }
/** /**
* Returns the shortest timed delay. This can be scaled up for * Returns the shortest timed delay. This can be scaled up for
* slow machines using the jsr166.delay.factor system property, * slow machines using the jsr166.delay.factor system property,
@ -685,12 +718,17 @@ public class JSR166TestCase extends TestCase {
LONG_DELAY_MS = SHORT_DELAY_MS * 200; LONG_DELAY_MS = SHORT_DELAY_MS * 200;
} }
private static final long TIMEOUT_DELAY_MS
= (long) (12.0 * Math.cbrt(delayFactor));
/** /**
* Returns a timeout in milliseconds to be used in tests that * Returns a timeout in milliseconds to be used in tests that verify
* verify that operations block or time out. * that operations block or time out. We want this to be longer
* than the OS scheduling quantum, but not too long, so don't scale
* linearly with delayFactor; we use "crazy" cube root instead.
*/ */
long timeoutMillis() { static long timeoutMillis() {
return SHORT_DELAY_MS / 4; return TIMEOUT_DELAY_MS;
} }
/** /**
@ -1084,9 +1122,30 @@ public class JSR166TestCase extends TestCase {
if (sm != null) System.setSecurityManager(sm); if (sm != null) System.setSecurityManager(sm);
} }
/**
* Checks that thread eventually enters the expected blocked thread state.
*/
void assertThreadBlocks(Thread thread, Thread.State expected) {
// always sleep at least 1 ms, with high probability avoiding
// transitory states
for (long retries = LONG_DELAY_MS * 3 / 4; retries-->0; ) {
try { delay(1); }
catch (InterruptedException fail) {
fail("Unexpected InterruptedException");
}
Thread.State s = thread.getState();
if (s == expected)
return;
else if (s == Thread.State.TERMINATED)
fail("Unexpected thread termination");
}
fail("timed out waiting for thread to enter thread state " + expected);
}
/** /**
* Checks that thread does not terminate within the default * Checks that thread does not terminate within the default
* millisecond delay of {@code timeoutMillis()}. * millisecond delay of {@code timeoutMillis()}.
* TODO: REMOVEME
*/ */
void assertThreadStaysAlive(Thread thread) { void assertThreadStaysAlive(Thread thread) {
assertThreadStaysAlive(thread, timeoutMillis()); assertThreadStaysAlive(thread, timeoutMillis());
@ -1094,6 +1153,7 @@ public class JSR166TestCase extends TestCase {
/** /**
* Checks that thread does not terminate within the given millisecond delay. * Checks that thread does not terminate within the given millisecond delay.
* TODO: REMOVEME
*/ */
void assertThreadStaysAlive(Thread thread, long millis) { void assertThreadStaysAlive(Thread thread, long millis) {
try { try {
@ -1108,6 +1168,7 @@ public class JSR166TestCase extends TestCase {
/** /**
* Checks that the threads do not terminate within the default * Checks that the threads do not terminate within the default
* millisecond delay of {@code timeoutMillis()}. * millisecond delay of {@code timeoutMillis()}.
* TODO: REMOVEME
*/ */
void assertThreadsStayAlive(Thread... threads) { void assertThreadsStayAlive(Thread... threads) {
assertThreadsStayAlive(timeoutMillis(), threads); assertThreadsStayAlive(timeoutMillis(), threads);
@ -1115,6 +1176,7 @@ public class JSR166TestCase extends TestCase {
/** /**
* Checks that the threads do not terminate within the given millisecond delay. * Checks that the threads do not terminate within the given millisecond delay.
* TODO: REMOVEME
*/ */
void assertThreadsStayAlive(long millis, Thread... threads) { void assertThreadsStayAlive(long millis, Thread... threads) {
try { try {
@ -1164,6 +1226,12 @@ public class JSR166TestCase extends TestCase {
fail("Should throw " + exceptionName); fail("Should throw " + exceptionName);
} }
/**
* The maximum number of consecutive spurious wakeups we should
* tolerate (from APIs like LockSupport.park) before failing a test.
*/
static final int MAX_SPURIOUS_WAKEUPS = 10;
/** /**
* The number of elements to place in collections, arrays, etc. * The number of elements to place in collections, arrays, etc.
*/ */
@ -1633,6 +1701,14 @@ public class JSR166TestCase extends TestCase {
} }
} }
public void await(CyclicBarrier barrier) {
try {
barrier.await(LONG_DELAY_MS, MILLISECONDS);
} catch (Throwable fail) {
threadUnexpectedException(fail);
}
}
// /** // /**
// * Spin-waits up to LONG_DELAY_MS until flag becomes true. // * Spin-waits up to LONG_DELAY_MS until flag becomes true.
// */ // */
@ -1656,28 +1732,6 @@ public class JSR166TestCase extends TestCase {
public String call() { throw new NullPointerException(); } public String call() { throw new NullPointerException(); }
} }
public static class CallableOne implements Callable<Integer> {
public Integer call() { return one; }
}
public class ShortRunnable extends CheckedRunnable {
protected void realRun() throws Throwable {
delay(SHORT_DELAY_MS);
}
}
public class ShortInterruptedRunnable extends CheckedInterruptedRunnable {
protected void realRun() throws InterruptedException {
delay(SHORT_DELAY_MS);
}
}
public class SmallRunnable extends CheckedRunnable {
protected void realRun() throws Throwable {
delay(SMALL_DELAY_MS);
}
}
public class SmallPossiblyInterruptedRunnable extends CheckedRunnable { public class SmallPossiblyInterruptedRunnable extends CheckedRunnable {
protected void realRun() { protected void realRun() {
try { try {
@ -1686,25 +1740,6 @@ public class JSR166TestCase extends TestCase {
} }
} }
public class SmallCallable extends CheckedCallable {
protected Object realCall() throws InterruptedException {
delay(SMALL_DELAY_MS);
return Boolean.TRUE;
}
}
public class MediumRunnable extends CheckedRunnable {
protected void realRun() throws Throwable {
delay(MEDIUM_DELAY_MS);
}
}
public class MediumInterruptedRunnable extends CheckedInterruptedRunnable {
protected void realRun() throws InterruptedException {
delay(MEDIUM_DELAY_MS);
}
}
public Runnable possiblyInterruptedRunnable(final long timeoutMillis) { public Runnable possiblyInterruptedRunnable(final long timeoutMillis) {
return new CheckedRunnable() { return new CheckedRunnable() {
protected void realRun() { protected void realRun() {
@ -1714,22 +1749,6 @@ public class JSR166TestCase extends TestCase {
}}; }};
} }
public class MediumPossiblyInterruptedRunnable extends CheckedRunnable {
protected void realRun() {
try {
delay(MEDIUM_DELAY_MS);
} catch (InterruptedException ok) {}
}
}
public class LongPossiblyInterruptedRunnable extends CheckedRunnable {
protected void realRun() {
try {
delay(LONG_DELAY_MS);
} catch (InterruptedException ok) {}
}
}
/** /**
* For use as ThreadFactory in constructors * For use as ThreadFactory in constructors
*/ */
@ -1743,59 +1762,6 @@ public class JSR166TestCase extends TestCase {
boolean isDone(); boolean isDone();
} }
public static TrackedRunnable trackedRunnable(final long timeoutMillis) {
return new TrackedRunnable() {
private volatile boolean done = false;
public boolean isDone() { return done; }
public void run() {
try {
delay(timeoutMillis);
done = true;
} catch (InterruptedException ok) {}
}
};
}
public static class TrackedShortRunnable implements Runnable {
public volatile boolean done = false;
public void run() {
try {
delay(SHORT_DELAY_MS);
done = true;
} catch (InterruptedException ok) {}
}
}
public static class TrackedSmallRunnable implements Runnable {
public volatile boolean done = false;
public void run() {
try {
delay(SMALL_DELAY_MS);
done = true;
} catch (InterruptedException ok) {}
}
}
public static class TrackedMediumRunnable implements Runnable {
public volatile boolean done = false;
public void run() {
try {
delay(MEDIUM_DELAY_MS);
done = true;
} catch (InterruptedException ok) {}
}
}
public static class TrackedLongRunnable implements Runnable {
public volatile boolean done = false;
public void run() {
try {
delay(LONG_DELAY_MS);
done = true;
} catch (InterruptedException ok) {}
}
}
public static class TrackedNoOpRunnable implements Runnable { public static class TrackedNoOpRunnable implements Runnable {
public volatile boolean done = false; public volatile boolean done = false;
public void run() { public void run() {
@ -1803,17 +1769,6 @@ public class JSR166TestCase extends TestCase {
} }
} }
public static class TrackedCallable implements Callable {
public volatile boolean done = false;
public Object call() {
try {
delay(SMALL_DELAY_MS);
done = true;
} catch (InterruptedException ok) {}
return Boolean.TRUE;
}
}
/** /**
* Analog of CheckedRunnable for RecursiveAction * Analog of CheckedRunnable for RecursiveAction
*/ */
@ -1880,7 +1835,7 @@ public class JSR166TestCase extends TestCase {
assertEquals(0, q.size()); assertEquals(0, q.size());
assertNull(q.peek()); assertNull(q.peek());
assertNull(q.poll()); assertNull(q.poll());
assertNull(q.poll(0, MILLISECONDS)); assertNull(q.poll(randomExpiredTimeout(), randomTimeUnit()));
assertEquals(q.toString(), "[]"); assertEquals(q.toString(), "[]");
assertTrue(Arrays.equals(q.toArray(), new Object[0])); assertTrue(Arrays.equals(q.toArray(), new Object[0]));
assertFalse(q.iterator().hasNext()); assertFalse(q.iterator().hasNext());
@ -2031,4 +1986,176 @@ public class JSR166TestCase extends TestCase {
static <T> void shuffle(T[] array) { static <T> void shuffle(T[] array) {
Collections.shuffle(Arrays.asList(array), ThreadLocalRandom.current()); Collections.shuffle(Arrays.asList(array), ThreadLocalRandom.current());
} }
// --- Shared assertions for Executor tests ---
/**
* Returns maximum number of tasks that can be submitted to given
* pool (with bounded queue) before saturation (when submission
* throws RejectedExecutionException).
*/
static final int saturatedSize(ThreadPoolExecutor pool) {
BlockingQueue<Runnable> q = pool.getQueue();
return pool.getMaximumPoolSize() + q.size() + q.remainingCapacity();
}
@SuppressWarnings("FutureReturnValueIgnored")
void assertNullTaskSubmissionThrowsNullPointerException(Executor e) {
try {
e.execute((Runnable) null);
shouldThrow();
} catch (NullPointerException success) {}
if (! (e instanceof ExecutorService)) return;
ExecutorService es = (ExecutorService) e;
try {
es.submit((Runnable) null);
shouldThrow();
} catch (NullPointerException success) {}
try {
es.submit((Runnable) null, Boolean.TRUE);
shouldThrow();
} catch (NullPointerException success) {}
try {
es.submit((Callable) null);
shouldThrow();
} catch (NullPointerException success) {}
if (! (e instanceof ScheduledExecutorService)) return;
ScheduledExecutorService ses = (ScheduledExecutorService) e;
try {
ses.schedule((Runnable) null,
randomTimeout(), randomTimeUnit());
shouldThrow();
} catch (NullPointerException success) {}
try {
ses.schedule((Callable) null,
randomTimeout(), randomTimeUnit());
shouldThrow();
} catch (NullPointerException success) {}
try {
ses.scheduleAtFixedRate((Runnable) null,
randomTimeout(), LONG_DELAY_MS, MILLISECONDS);
shouldThrow();
} catch (NullPointerException success) {}
try {
ses.scheduleWithFixedDelay((Runnable) null,
randomTimeout(), LONG_DELAY_MS, MILLISECONDS);
shouldThrow();
} catch (NullPointerException success) {}
}
void setRejectedExecutionHandler(
ThreadPoolExecutor p, RejectedExecutionHandler handler) {
p.setRejectedExecutionHandler(handler);
assertSame(handler, p.getRejectedExecutionHandler());
}
void assertTaskSubmissionsAreRejected(ThreadPoolExecutor p) {
final RejectedExecutionHandler savedHandler = p.getRejectedExecutionHandler();
final long savedTaskCount = p.getTaskCount();
final long savedCompletedTaskCount = p.getCompletedTaskCount();
final int savedQueueSize = p.getQueue().size();
final boolean stock = (p.getClass().getClassLoader() == null);
Runnable r = () -> {};
Callable<Boolean> c = () -> Boolean.TRUE;
class Recorder implements RejectedExecutionHandler {
public volatile Runnable r = null;
public volatile ThreadPoolExecutor p = null;
public void reset() { r = null; p = null; }
public void rejectedExecution(Runnable r, ThreadPoolExecutor p) {
assertNull(this.r);
assertNull(this.p);
this.r = r;
this.p = p;
}
}
// check custom handler is invoked exactly once per task
Recorder recorder = new Recorder();
setRejectedExecutionHandler(p, recorder);
for (int i = 2; i--> 0; ) {
recorder.reset();
p.execute(r);
if (stock && p.getClass() == ThreadPoolExecutor.class)
assertSame(r, recorder.r);
assertSame(p, recorder.p);
recorder.reset();
assertFalse(p.submit(r).isDone());
if (stock) assertTrue(!((FutureTask) recorder.r).isDone());
assertSame(p, recorder.p);
recorder.reset();
assertFalse(p.submit(r, Boolean.TRUE).isDone());
if (stock) assertTrue(!((FutureTask) recorder.r).isDone());
assertSame(p, recorder.p);
recorder.reset();
assertFalse(p.submit(c).isDone());
if (stock) assertTrue(!((FutureTask) recorder.r).isDone());
assertSame(p, recorder.p);
if (p instanceof ScheduledExecutorService) {
ScheduledExecutorService s = (ScheduledExecutorService) p;
ScheduledFuture<?> future;
recorder.reset();
future = s.schedule(r, randomTimeout(), randomTimeUnit());
assertFalse(future.isDone());
if (stock) assertTrue(!((FutureTask) recorder.r).isDone());
assertSame(p, recorder.p);
recorder.reset();
future = s.schedule(c, randomTimeout(), randomTimeUnit());
assertFalse(future.isDone());
if (stock) assertTrue(!((FutureTask) recorder.r).isDone());
assertSame(p, recorder.p);
recorder.reset();
future = s.scheduleAtFixedRate(r, randomTimeout(), LONG_DELAY_MS, MILLISECONDS);
assertFalse(future.isDone());
if (stock) assertTrue(!((FutureTask) recorder.r).isDone());
assertSame(p, recorder.p);
recorder.reset();
future = s.scheduleWithFixedDelay(r, randomTimeout(), LONG_DELAY_MS, MILLISECONDS);
assertFalse(future.isDone());
if (stock) assertTrue(!((FutureTask) recorder.r).isDone());
assertSame(p, recorder.p);
}
}
// Checking our custom handler above should be sufficient, but
// we add some integration tests of standard handlers.
final AtomicReference<Thread> thread = new AtomicReference<>();
final Runnable setThread = () -> thread.set(Thread.currentThread());
setRejectedExecutionHandler(p, new ThreadPoolExecutor.AbortPolicy());
try {
p.execute(setThread);
shouldThrow();
} catch (RejectedExecutionException success) {}
assertNull(thread.get());
setRejectedExecutionHandler(p, new ThreadPoolExecutor.DiscardPolicy());
p.execute(setThread);
assertNull(thread.get());
setRejectedExecutionHandler(p, new ThreadPoolExecutor.CallerRunsPolicy());
p.execute(setThread);
if (p.isShutdown())
assertNull(thread.get());
else
assertSame(Thread.currentThread(), thread.get());
setRejectedExecutionHandler(p, savedHandler);
// check that pool was not perturbed by handlers
assertEquals(savedTaskCount, p.getTaskCount());
assertEquals(savedCompletedTaskCount, p.getCompletedTaskCount());
assertEquals(savedQueueSize, p.getQueue().size());
}
} }

View File

@ -469,7 +469,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
} }
/** /**
* push succeeds if not full; throws ISE if full * push succeeds if not full; throws IllegalStateException if full
*/ */
public void testPush() { public void testPush() {
LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE); LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE);
@ -519,7 +519,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
} }
/** /**
* add succeeds if not full; throws ISE if full * add succeeds if not full; throws IllegalStateException if full
*/ */
public void testAdd() { public void testAdd() {
LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE); LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE);
@ -533,7 +533,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
} }
/** /**
* addAll(this) throws IAE * addAll(this) throws IllegalArgumentException
*/ */
public void testAddAllSelf() { public void testAddAllSelf() {
LinkedBlockingDeque q = populatedDeque(SIZE); LinkedBlockingDeque q = populatedDeque(SIZE);
@ -631,7 +631,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
assertEquals(SIZE, q.size()); assertEquals(SIZE, q.size());
@ -653,6 +653,13 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
pleaseTake.countDown(); pleaseTake.countDown();
q.put(86); q.put(86);
Thread.currentThread().interrupt();
try {
q.put(99);
shouldThrow();
} catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
pleaseInterrupt.countDown(); pleaseInterrupt.countDown();
try { try {
q.put(99); q.put(99);
@ -666,7 +673,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
assertEquals(0, q.take()); assertEquals(0, q.take());
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
assertEquals(0, q.remainingCapacity()); assertEquals(0, q.remainingCapacity());
@ -675,7 +682,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
/** /**
* timed offer times out if full and elements not taken * timed offer times out if full and elements not taken
*/ */
public void testTimedOffer() throws InterruptedException { public void testTimedOffer() {
final LinkedBlockingDeque q = new LinkedBlockingDeque(2); final LinkedBlockingDeque q = new LinkedBlockingDeque(2);
final CountDownLatch pleaseInterrupt = new CountDownLatch(1); final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
@ -685,15 +692,24 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
long startTime = System.nanoTime(); long startTime = System.nanoTime();
assertFalse(q.offer(new Object(), timeoutMillis(), MILLISECONDS)); assertFalse(q.offer(new Object(), timeoutMillis(), MILLISECONDS));
assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
Thread.currentThread().interrupt();
try {
q.offer(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS);
shouldThrow();
} catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
pleaseInterrupt.countDown(); pleaseInterrupt.countDown();
try { try {
q.offer(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS); q.offer(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS);
shouldThrow(); shouldThrow();
} catch (InterruptedException success) {} } catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -716,9 +732,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
final CountDownLatch pleaseInterrupt = new CountDownLatch(1); final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException { public void realRun() throws InterruptedException {
for (int i = 0; i < SIZE; ++i) { for (int i = 0; i < SIZE; i++) assertEquals(i, q.take());
assertEquals(i, q.take());
}
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
try { try {
@ -736,7 +750,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -785,24 +799,32 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
*/ */
public void testInterruptedTimedPoll() throws InterruptedException { public void testInterruptedTimedPoll() throws InterruptedException {
final BlockingQueue<Integer> q = populatedDeque(SIZE); final BlockingQueue<Integer> q = populatedDeque(SIZE);
final CountDownLatch aboutToWait = new CountDownLatch(1); final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException { public void realRun() throws InterruptedException {
long startTime = System.nanoTime(); long startTime = System.nanoTime();
for (int i = 0; i < SIZE; ++i) { for (int i = 0; i < SIZE; i++)
assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS)); assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS));
}
aboutToWait.countDown(); Thread.currentThread().interrupt();
try { try {
q.poll(LONG_DELAY_MS, MILLISECONDS); q.poll(LONG_DELAY_MS, MILLISECONDS);
shouldThrow(); shouldThrow();
} catch (InterruptedException success) { } catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
pleaseInterrupt.countDown();
try {
q.poll(LONG_DELAY_MS, MILLISECONDS);
shouldThrow();
} catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
}
}}); }});
await(aboutToWait); await(pleaseInterrupt);
waitForThreadToEnterWaitState(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
checkEmpty(q); checkEmpty(q);
@ -861,7 +883,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
assertEquals(SIZE, q.size()); assertEquals(SIZE, q.size());
@ -896,7 +918,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
assertEquals(capacity - 1, q.take()); assertEquals(capacity - 1, q.take());
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
assertEquals(0, q.remainingCapacity()); assertEquals(0, q.remainingCapacity());
@ -905,7 +927,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
/** /**
* timed offerFirst times out if full and elements not taken * timed offerFirst times out if full and elements not taken
*/ */
public void testTimedOfferFirst() throws InterruptedException { public void testTimedOfferFirst() {
final LinkedBlockingDeque q = new LinkedBlockingDeque(2); final LinkedBlockingDeque q = new LinkedBlockingDeque(2);
final CountDownLatch pleaseInterrupt = new CountDownLatch(1); final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
@ -915,15 +937,24 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
long startTime = System.nanoTime(); long startTime = System.nanoTime();
assertFalse(q.offerFirst(new Object(), timeoutMillis(), MILLISECONDS)); assertFalse(q.offerFirst(new Object(), timeoutMillis(), MILLISECONDS));
assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
Thread.currentThread().interrupt();
try {
q.offerFirst(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS);
shouldThrow();
} catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
pleaseInterrupt.countDown(); pleaseInterrupt.countDown();
try { try {
q.offerFirst(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS); q.offerFirst(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS);
shouldThrow(); shouldThrow();
} catch (InterruptedException success) {} } catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -955,7 +986,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
}}); }});
await(threadStarted); await(threadStarted);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -996,7 +1027,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
}}); }});
await(threadStarted); await(threadStarted);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -1028,9 +1059,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
final CountDownLatch pleaseInterrupt = new CountDownLatch(1); final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException { public void realRun() throws InterruptedException {
for (int i = 0; i < SIZE; ++i) { for (int i = 0; i < SIZE; i++) assertEquals(i, q.takeFirst());
assertEquals(i, q.takeFirst());
}
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
try { try {
@ -1048,7 +1077,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -1090,9 +1119,8 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException { public void realRun() throws InterruptedException {
long startTime = System.nanoTime(); long startTime = System.nanoTime();
for (int i = 0; i < SIZE; ++i) { for (int i = 0; i < SIZE; i++)
assertEquals(i, q.pollFirst(LONG_DELAY_MS, MILLISECONDS)); assertEquals(i, q.pollFirst(LONG_DELAY_MS, MILLISECONDS));
}
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
try { try {
@ -1107,11 +1135,12 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
shouldThrow(); shouldThrow();
} catch (InterruptedException success) {} } catch (InterruptedException success) {}
assertFalse(Thread.interrupted()); assertFalse(Thread.interrupted());
assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -1144,6 +1173,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
q.pollFirst(LONG_DELAY_MS, MILLISECONDS); q.pollFirst(LONG_DELAY_MS, MILLISECONDS);
shouldThrow(); shouldThrow();
} catch (InterruptedException success) {} } catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
}}); }});
@ -1152,7 +1182,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
assertTrue(q.offerFirst(zero, LONG_DELAY_MS, MILLISECONDS)); assertTrue(q.offerFirst(zero, LONG_DELAY_MS, MILLISECONDS));
assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
barrier.await(); barrier.await();
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -1210,7 +1240,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
assertEquals(SIZE, q.size()); assertEquals(SIZE, q.size());
@ -1232,6 +1262,13 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
pleaseTake.countDown(); pleaseTake.countDown();
q.putLast(86); q.putLast(86);
Thread.currentThread().interrupt();
try {
q.putLast(99);
shouldThrow();
} catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
pleaseInterrupt.countDown(); pleaseInterrupt.countDown();
try { try {
q.putLast(99); q.putLast(99);
@ -1245,7 +1282,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
assertEquals(0, q.take()); assertEquals(0, q.take());
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
assertEquals(0, q.remainingCapacity()); assertEquals(0, q.remainingCapacity());
@ -1254,7 +1291,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
/** /**
* timed offerLast times out if full and elements not taken * timed offerLast times out if full and elements not taken
*/ */
public void testTimedOfferLast() throws InterruptedException { public void testTimedOfferLast() {
final LinkedBlockingDeque q = new LinkedBlockingDeque(2); final LinkedBlockingDeque q = new LinkedBlockingDeque(2);
final CountDownLatch pleaseInterrupt = new CountDownLatch(1); final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
@ -1264,6 +1301,13 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
long startTime = System.nanoTime(); long startTime = System.nanoTime();
assertFalse(q.offerLast(new Object(), timeoutMillis(), MILLISECONDS)); assertFalse(q.offerLast(new Object(), timeoutMillis(), MILLISECONDS));
assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
Thread.currentThread().interrupt();
try {
q.offerLast(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS);
shouldThrow();
} catch (InterruptedException success) {}
pleaseInterrupt.countDown(); pleaseInterrupt.countDown();
try { try {
q.offerLast(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS); q.offerLast(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS);
@ -1272,7 +1316,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -1295,9 +1339,8 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
final CountDownLatch pleaseInterrupt = new CountDownLatch(1); final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException { public void realRun() throws InterruptedException {
for (int i = 0; i < SIZE; ++i) { for (int i = 0; i < SIZE; i++)
assertEquals(SIZE - i - 1, q.takeLast()); assertEquals(SIZE - i - 1, q.takeLast());
}
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
try { try {
@ -1315,7 +1358,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -1357,10 +1400,9 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException { public void realRun() throws InterruptedException {
long startTime = System.nanoTime(); long startTime = System.nanoTime();
for (int i = 0; i < SIZE; ++i) { for (int i = 0; i < SIZE; i++)
assertEquals(SIZE - i - 1, assertEquals(SIZE - i - 1,
q.pollLast(LONG_DELAY_MS, MILLISECONDS)); q.pollLast(LONG_DELAY_MS, MILLISECONDS));
}
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
try { try {
@ -1380,7 +1422,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
checkEmpty(q); checkEmpty(q);
@ -1426,7 +1468,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase {
assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
barrier.await(); barrier.await();
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }

View File

@ -319,7 +319,7 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
assertEquals(SIZE, q.size()); assertEquals(SIZE, q.size());
@ -341,6 +341,13 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
pleaseTake.countDown(); pleaseTake.countDown();
q.put(86); q.put(86);
Thread.currentThread().interrupt();
try {
q.put(99);
shouldThrow();
} catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
pleaseInterrupt.countDown(); pleaseInterrupt.countDown();
try { try {
q.put(99); q.put(99);
@ -354,7 +361,7 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
assertEquals(0, q.take()); assertEquals(0, q.take());
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
assertEquals(0, q.remainingCapacity()); assertEquals(0, q.remainingCapacity());
@ -370,18 +377,28 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
public void realRun() throws InterruptedException { public void realRun() throws InterruptedException {
q.put(new Object()); q.put(new Object());
q.put(new Object()); q.put(new Object());
long startTime = System.nanoTime(); long startTime = System.nanoTime();
assertFalse(q.offer(new Object(), timeoutMillis(), MILLISECONDS)); assertFalse(q.offer(new Object(), timeoutMillis(), MILLISECONDS));
assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
Thread.currentThread().interrupt();
try {
q.offer(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS);
shouldThrow();
} catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
pleaseInterrupt.countDown(); pleaseInterrupt.countDown();
try { try {
q.offer(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS); q.offer(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS);
shouldThrow(); shouldThrow();
} catch (InterruptedException success) {} } catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -404,9 +421,7 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
final CountDownLatch pleaseInterrupt = new CountDownLatch(1); final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException { public void realRun() throws InterruptedException {
for (int i = 0; i < SIZE; ++i) { for (int i = 0; i < SIZE; i++) assertEquals(i, q.take());
assertEquals(i, q.take());
}
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
try { try {
@ -424,7 +439,7 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -473,24 +488,32 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
*/ */
public void testInterruptedTimedPoll() throws InterruptedException { public void testInterruptedTimedPoll() throws InterruptedException {
final BlockingQueue<Integer> q = populatedQueue(SIZE); final BlockingQueue<Integer> q = populatedQueue(SIZE);
final CountDownLatch aboutToWait = new CountDownLatch(1); final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException { public void realRun() throws InterruptedException {
long startTime = System.nanoTime(); long startTime = System.nanoTime();
for (int i = 0; i < SIZE; ++i) { for (int i = 0; i < SIZE; i++)
assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS)); assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS));
}
aboutToWait.countDown(); Thread.currentThread().interrupt();
try { try {
q.poll(LONG_DELAY_MS, MILLISECONDS); q.poll(LONG_DELAY_MS, MILLISECONDS);
shouldThrow(); shouldThrow();
} catch (InterruptedException success) { } catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
pleaseInterrupt.countDown();
try {
q.poll(LONG_DELAY_MS, MILLISECONDS);
shouldThrow();
} catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
}
}}); }});
await(aboutToWait); await(pleaseInterrupt);
waitForThreadToEnterWaitState(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
checkEmpty(q); checkEmpty(q);

View File

@ -236,9 +236,7 @@ public class LinkedTransferQueueTest extends JSR166TestCase {
final CountDownLatch pleaseInterrupt = new CountDownLatch(1); final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException { public void realRun() throws InterruptedException {
for (int i = 0; i < SIZE; ++i) { for (int i = 0; i < SIZE; i++) assertEquals(i, q.take());
assertEquals(i, q.take());
}
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
try { try {
@ -256,7 +254,7 @@ public class LinkedTransferQueueTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -307,22 +305,32 @@ public class LinkedTransferQueueTest extends JSR166TestCase {
*/ */
public void testInterruptedTimedPoll() throws InterruptedException { public void testInterruptedTimedPoll() throws InterruptedException {
final BlockingQueue<Integer> q = populatedQueue(SIZE); final BlockingQueue<Integer> q = populatedQueue(SIZE);
final CountDownLatch aboutToWait = new CountDownLatch(1); final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException { public void realRun() throws InterruptedException {
long startTime = System.nanoTime(); long startTime = System.nanoTime();
for (int i = 0; i < SIZE; ++i) for (int i = 0; i < SIZE; i++)
assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS)); assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS));
aboutToWait.countDown();
Thread.currentThread().interrupt();
try { try {
q.poll(LONG_DELAY_MS, MILLISECONDS); q.poll(LONG_DELAY_MS, MILLISECONDS);
shouldThrow(); shouldThrow();
} catch (InterruptedException success) {} } catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
pleaseInterrupt.countDown();
try {
q.poll(LONG_DELAY_MS, MILLISECONDS);
shouldThrow();
} catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
}}); }});
await(aboutToWait); await(pleaseInterrupt);
waitForThreadToEnterWaitState(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
checkEmpty(q); checkEmpty(q);
@ -344,6 +352,7 @@ public class LinkedTransferQueueTest extends JSR166TestCase {
q.poll(LONG_DELAY_MS, MILLISECONDS); q.poll(LONG_DELAY_MS, MILLISECONDS);
shouldThrow(); shouldThrow();
} catch (InterruptedException success) {} } catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
}}); }});
@ -990,7 +999,7 @@ public class LinkedTransferQueueTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
checkEmpty(q); checkEmpty(q);

View File

@ -71,9 +71,7 @@ public class LockSupportTest extends JSR166TestCase {
void park() { void park() {
LockSupport.park(); LockSupport.park();
} }
void park(long millis) { Thread.State parkedState() { return Thread.State.WAITING; }
throw new UnsupportedOperationException();
}
}, },
parkUntil() { parkUntil() {
void park(long millis) { void park(long millis) {
@ -89,9 +87,7 @@ public class LockSupportTest extends JSR166TestCase {
void park() { void park() {
LockSupport.park(theBlocker()); LockSupport.park(theBlocker());
} }
void park(long millis) { Thread.State parkedState() { return Thread.State.WAITING; }
throw new UnsupportedOperationException();
}
}, },
parkUntilBlocker() { parkUntilBlocker() {
void park(long millis) { void park(long millis) {
@ -106,7 +102,10 @@ public class LockSupportTest extends JSR166TestCase {
}; };
void park() { park(2 * LONG_DELAY_MS); } void park() { park(2 * LONG_DELAY_MS); }
abstract void park(long millis); void park(long millis) {
throw new UnsupportedOperationException();
}
Thread.State parkedState() { return Thread.State.TIMED_WAITING; }
/** Returns a deadline to use with parkUntil. */ /** Returns a deadline to use with parkUntil. */
long deadline(long millis) { long deadline(long millis) {
@ -213,14 +212,16 @@ public class LockSupportTest extends JSR166TestCase {
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() { public void realRun() {
pleaseInterrupt.countDown(); pleaseInterrupt.countDown();
do { for (int tries = MAX_SPURIOUS_WAKEUPS; tries-->0; ) {
parkMethod.park(); parkMethod.park();
// park may return spuriously if (Thread.interrupted())
} while (! Thread.currentThread().isInterrupted()); return;
}
fail("too many consecutive spurious wakeups?");
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, parkMethod.parkedState());
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -248,20 +249,17 @@ public class LockSupportTest extends JSR166TestCase {
} }
public void testParkAfterInterrupt(final ParkMethod parkMethod) { public void testParkAfterInterrupt(final ParkMethod parkMethod) {
final CountDownLatch pleaseInterrupt = new CountDownLatch(1); final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
final AtomicBoolean pleasePark = new AtomicBoolean(false);
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() throws Exception { public void realRun() throws Exception {
pleaseInterrupt.countDown(); pleaseInterrupt.countDown();
while (!pleasePark.get()) while (!Thread.currentThread().isInterrupted())
Thread.yield(); Thread.yield();
assertTrue(Thread.currentThread().isInterrupted());
parkMethod.park(); parkMethod.park();
assertTrue(Thread.currentThread().isInterrupted()); assertTrue(Thread.interrupted());
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
t.interrupt(); t.interrupt();
pleasePark.set(true);
awaitTermination(t); awaitTermination(t);
} }
@ -283,13 +281,13 @@ public class LockSupportTest extends JSR166TestCase {
public void testParkTimesOut(final ParkMethod parkMethod) { public void testParkTimesOut(final ParkMethod parkMethod) {
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() { public void realRun() {
for (;;) { for (int tries = MAX_SPURIOUS_WAKEUPS; tries-->0; ) {
long startTime = System.nanoTime(); long startTime = System.nanoTime();
parkMethod.park(timeoutMillis()); parkMethod.park(timeoutMillis());
// park may return spuriously
if (millisElapsedSince(startTime) >= timeoutMillis()) if (millisElapsedSince(startTime) >= timeoutMillis())
return; return;
} }
fail("too many consecutive spurious wakeups?");
}}); }});
awaitTermination(t); awaitTermination(t);
@ -323,12 +321,14 @@ public class LockSupportTest extends JSR166TestCase {
public void realRun() { public void realRun() {
Thread t = Thread.currentThread(); Thread t = Thread.currentThread();
started.countDown(); started.countDown();
do { for (int tries = MAX_SPURIOUS_WAKEUPS; tries-->0; ) {
assertNull(LockSupport.getBlocker(t)); assertNull(LockSupport.getBlocker(t));
parkMethod.park(); parkMethod.park();
assertNull(LockSupport.getBlocker(t)); assertNull(LockSupport.getBlocker(t));
// park may return spuriously if (Thread.interrupted())
} while (! Thread.currentThread().isInterrupted()); return;
}
fail("too many consecutive spurious wakeups?");
}}); }});
long startTime = System.nanoTime(); long startTime = System.nanoTime();
@ -344,6 +344,8 @@ public class LockSupportTest extends JSR166TestCase {
assertNull(x); // ok assertNull(x); // ok
if (millisElapsedSince(startTime) > LONG_DELAY_MS) if (millisElapsedSince(startTime) > LONG_DELAY_MS)
fail("timed out"); fail("timed out");
if (t.getState() == Thread.State.TERMINATED)
break;
Thread.yield(); Thread.yield();
} }
} }

View File

@ -34,6 +34,7 @@
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Phaser; import java.util.concurrent.Phaser;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.LongAccumulator; import java.util.concurrent.atomic.LongAccumulator;
import junit.framework.Test; import junit.framework.Test;
@ -48,135 +49,124 @@ public class LongAccumulatorTest extends JSR166TestCase {
} }
/** /**
* default constructed initializes to zero * new instance initialized to supplied identity
*/ */
public void testConstructor() { public void testConstructor() {
LongAccumulator ai = new LongAccumulator(Long::max, 0L); for (long identity : new long[] { Long.MIN_VALUE, 0, Long.MAX_VALUE })
assertEquals(0, ai.get()); assertEquals(identity,
new LongAccumulator(Long::max, identity).get());
} }
/** /**
* accumulate accumulates given value to current, and get returns current value * accumulate accumulates given value to current, and get returns current value
*/ */
public void testAccumulateAndGet() { public void testAccumulateAndGet() {
LongAccumulator ai = new LongAccumulator(Long::max, 0L); LongAccumulator acc = new LongAccumulator(Long::max, 0L);
ai.accumulate(2); acc.accumulate(2);
assertEquals(2, ai.get()); assertEquals(2, acc.get());
ai.accumulate(-4); acc.accumulate(-4);
assertEquals(2, ai.get()); assertEquals(2, acc.get());
ai.accumulate(4); acc.accumulate(4);
assertEquals(4, ai.get()); assertEquals(4, acc.get());
} }
/** /**
* reset() causes subsequent get() to return zero * reset() causes subsequent get() to return zero
*/ */
public void testReset() { public void testReset() {
LongAccumulator ai = new LongAccumulator(Long::max, 0L); LongAccumulator acc = new LongAccumulator(Long::max, 0L);
ai.accumulate(2); acc.accumulate(2);
assertEquals(2, ai.get()); assertEquals(2, acc.get());
ai.reset(); acc.reset();
assertEquals(0, ai.get()); assertEquals(0, acc.get());
} }
/** /**
* getThenReset() returns current value; subsequent get() returns zero * getThenReset() returns current value; subsequent get() returns zero
*/ */
public void testGetThenReset() { public void testGetThenReset() {
LongAccumulator ai = new LongAccumulator(Long::max, 0L); LongAccumulator acc = new LongAccumulator(Long::max, 0L);
ai.accumulate(2); acc.accumulate(2);
assertEquals(2, ai.get()); assertEquals(2, acc.get());
assertEquals(2, ai.getThenReset()); assertEquals(2, acc.getThenReset());
assertEquals(0, ai.get()); assertEquals(0, acc.get());
} }
/** /**
* toString returns current value. * toString returns current value.
*/ */
public void testToString() { public void testToString() {
LongAccumulator ai = new LongAccumulator(Long::max, 0L); LongAccumulator acc = new LongAccumulator(Long::max, 0L);
assertEquals("0", ai.toString()); assertEquals("0", acc.toString());
ai.accumulate(1); acc.accumulate(1);
assertEquals(Long.toString(1), ai.toString()); assertEquals(Long.toString(1), acc.toString());
} }
/** /**
* intValue returns current value. * intValue returns current value.
*/ */
public void testIntValue() { public void testIntValue() {
LongAccumulator ai = new LongAccumulator(Long::max, 0L); LongAccumulator acc = new LongAccumulator(Long::max, 0L);
assertEquals(0, ai.intValue()); assertEquals(0, acc.intValue());
ai.accumulate(1); acc.accumulate(1);
assertEquals(1, ai.intValue()); assertEquals(1, acc.intValue());
} }
/** /**
* longValue returns current value. * longValue returns current value.
*/ */
public void testLongValue() { public void testLongValue() {
LongAccumulator ai = new LongAccumulator(Long::max, 0L); LongAccumulator acc = new LongAccumulator(Long::max, 0L);
assertEquals(0, ai.longValue()); assertEquals(0, acc.longValue());
ai.accumulate(1); acc.accumulate(1);
assertEquals(1, ai.longValue()); assertEquals(1, acc.longValue());
} }
/** /**
* floatValue returns current value. * floatValue returns current value.
*/ */
public void testFloatValue() { public void testFloatValue() {
LongAccumulator ai = new LongAccumulator(Long::max, 0L); LongAccumulator acc = new LongAccumulator(Long::max, 0L);
assertEquals(0.0f, ai.floatValue()); assertEquals(0.0f, acc.floatValue());
ai.accumulate(1); acc.accumulate(1);
assertEquals(1.0f, ai.floatValue()); assertEquals(1.0f, acc.floatValue());
} }
/** /**
* doubleValue returns current value. * doubleValue returns current value.
*/ */
public void testDoubleValue() { public void testDoubleValue() {
LongAccumulator ai = new LongAccumulator(Long::max, 0L); LongAccumulator acc = new LongAccumulator(Long::max, 0L);
assertEquals(0.0, ai.doubleValue()); assertEquals(0.0, acc.doubleValue());
ai.accumulate(1); acc.accumulate(1);
assertEquals(1.0, ai.doubleValue()); assertEquals(1.0, acc.doubleValue());
} }
/** /**
* accumulates by multiple threads produce correct result * accumulates by multiple threads produce correct result
*/ */
public void testAccumulateAndGetMT() { public void testAccumulateAndGetMT() {
final int incs = 1000000; final LongAccumulator acc
final int nthreads = 4; = new LongAccumulator((x, y) -> x + y, 0L);
final ExecutorService pool = Executors.newCachedThreadPool(); final int nThreads = ThreadLocalRandom.current().nextInt(1, 5);
LongAccumulator a = new LongAccumulator(Long::max, 0L); final Phaser phaser = new Phaser(nThreads + 1);
Phaser phaser = new Phaser(nthreads + 1); final int incs = 1_000_000;
for (int i = 0; i < nthreads; ++i) final long total = nThreads * incs/2L * (incs - 1); // Gauss
pool.execute(new AccTask(a, phaser, incs)); final Runnable task = () -> {
phaser.arriveAndAwaitAdvance(); phaser.arriveAndAwaitAdvance();
phaser.arriveAndAwaitAdvance(); for (int i = 0; i < incs; i++) {
long expected = incs - 1; acc.accumulate((long) i);
long result = a.get(); assertTrue(acc.get() <= total);
assertEquals(expected, result);
pool.shutdown();
} }
static final class AccTask implements Runnable {
final LongAccumulator acc;
final Phaser phaser;
final int incs;
volatile long result;
AccTask(LongAccumulator acc, Phaser phaser, int incs) {
this.acc = acc;
this.phaser = phaser;
this.incs = incs;
}
public void run() {
phaser.arriveAndAwaitAdvance();
LongAccumulator a = acc;
for (int i = 0; i < incs; ++i)
a.accumulate(i);
result = a.get();
phaser.arrive(); phaser.arrive();
};
final ExecutorService p = Executors.newCachedThreadPool();
try (PoolCleaner cleaner = cleaner(p)) {
for (int i = nThreads; i-->0; )
p.execute(task);
phaser.arriveAndAwaitAdvance();
phaser.arriveAndAwaitAdvance();
assertEquals(total, acc.get());
} }
} }

View File

@ -520,7 +520,8 @@ public class PhaserTest extends JSR166TestCase {
await(pleaseInterrupt); await(pleaseInterrupt);
assertState(phaser, 0, 1, 1); assertState(phaser, 0, 1, 1);
assertThreadsStayAlive(t1, t2); assertThreadBlocks(t1, Thread.State.WAITING);
assertThreadBlocks(t2, Thread.State.TIMED_WAITING);
t1.interrupt(); t1.interrupt();
t2.interrupt(); t2.interrupt();
awaitTermination(t1); awaitTermination(t1);
@ -550,7 +551,7 @@ public class PhaserTest extends JSR166TestCase {
}}); }});
await(pleaseArrive); await(pleaseArrive);
waitForThreadToEnterWaitState(t); assertThreadBlocks(t, Thread.State.WAITING);
assertEquals(0, phaser.arrive()); assertEquals(0, phaser.arrive());
awaitTermination(t); awaitTermination(t);
@ -578,7 +579,7 @@ public class PhaserTest extends JSR166TestCase {
}}); }});
await(pleaseArrive); await(pleaseArrive);
waitForThreadToEnterWaitState(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
assertEquals(0, phaser.arrive()); assertEquals(0, phaser.arrive());
awaitTermination(t); awaitTermination(t);
@ -607,7 +608,7 @@ public class PhaserTest extends JSR166TestCase {
}}); }});
await(pleaseArrive); await(pleaseArrive);
waitForThreadToEnterWaitState(t); assertThreadBlocks(t, Thread.State.WAITING);
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
assertEquals(1, phaser.arriveAndAwaitAdvance()); assertEquals(1, phaser.arriveAndAwaitAdvance());
assertTrue(Thread.interrupted()); assertTrue(Thread.interrupted());
@ -632,7 +633,7 @@ public class PhaserTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
waitForThreadToEnterWaitState(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
assertEquals(1, phaser.arriveAndAwaitAdvance()); assertEquals(1, phaser.arriveAndAwaitAdvance());
@ -807,7 +808,7 @@ public class PhaserTest extends JSR166TestCase {
assertEquals(THREADS, phaser.getArrivedParties()); assertEquals(THREADS, phaser.getArrivedParties());
assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
for (Thread thread : threads) for (Thread thread : threads)
waitForThreadToEnterWaitState(thread); assertThreadBlocks(thread, Thread.State.WAITING);
for (Thread thread : threads) for (Thread thread : threads)
assertTrue(thread.isAlive()); assertTrue(thread.isAlive());
assertState(phaser, 0, THREADS + 1, 1); assertState(phaser, 0, THREADS + 1, 1);

View File

@ -117,7 +117,7 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
} }
/** /**
* Constructor throws IAE if capacity argument nonpositive * Constructor throws IllegalArgumentException if capacity argument nonpositive
*/ */
public void testConstructor2() { public void testConstructor2() {
try { try {
@ -256,7 +256,7 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
} }
/** /**
* addAll(this) throws IAE * addAll(this) throws IllegalArgumentException
*/ */
public void testAddAllSelf() { public void testAddAllSelf() {
PriorityBlockingQueue q = populatedQueue(SIZE); PriorityBlockingQueue q = populatedQueue(SIZE);
@ -329,7 +329,7 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
/** /**
* timed offer does not time out * timed offer does not time out
*/ */
public void testTimedOffer() throws InterruptedException { public void testTimedOffer() {
final PriorityBlockingQueue q = new PriorityBlockingQueue(2); final PriorityBlockingQueue q = new PriorityBlockingQueue(2);
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() { public void realRun() {
@ -360,9 +360,7 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
final CountDownLatch pleaseInterrupt = new CountDownLatch(1); final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException { public void realRun() throws InterruptedException {
for (int i = 0; i < SIZE; ++i) { for (int i = 0; i < SIZE; i++) assertEquals(i, q.take());
assertEquals(i, q.take());
}
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
try { try {
@ -380,7 +378,7 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -429,24 +427,32 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
*/ */
public void testInterruptedTimedPoll() throws InterruptedException { public void testInterruptedTimedPoll() throws InterruptedException {
final BlockingQueue<Integer> q = populatedQueue(SIZE); final BlockingQueue<Integer> q = populatedQueue(SIZE);
final CountDownLatch aboutToWait = new CountDownLatch(1); final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException { public void realRun() throws InterruptedException {
long startTime = System.nanoTime(); long startTime = System.nanoTime();
for (int i = 0; i < SIZE; ++i) { for (int i = 0; i < SIZE; i++)
assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS)); assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS));
}
aboutToWait.countDown(); Thread.currentThread().interrupt();
try { try {
q.poll(LONG_DELAY_MS, MILLISECONDS); q.poll(LONG_DELAY_MS, MILLISECONDS);
shouldThrow(); shouldThrow();
} catch (InterruptedException success) { } catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
pleaseInterrupt.countDown();
try {
q.poll(LONG_DELAY_MS, MILLISECONDS);
shouldThrow();
} catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
}
}}); }});
await(aboutToWait); await(pleaseInterrupt);
waitForThreadToEnterWaitState(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }

View File

@ -90,7 +90,7 @@ public class PriorityQueueTest extends JSR166TestCase {
} }
/** /**
* Constructor throws IAE if capacity argument nonpositive * Constructor throws IllegalArgumentException if capacity argument nonpositive
*/ */
public void testConstructor2() { public void testConstructor2() {
try { try {

View File

@ -31,7 +31,7 @@
* http://creativecommons.org/publicdomain/zero/1.0/ * http://creativecommons.org/publicdomain/zero/1.0/
*/ */
import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
@ -100,14 +100,14 @@ public class RecursiveActionTest extends JSR166TestCase {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
try { try {
a.get(5L, SECONDS); a.get(randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (InterruptedException success) { } catch (InterruptedException success) {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
} }
try { try {
a.get(0L, SECONDS); a.get(randomExpiredTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (TimeoutException success) { } catch (TimeoutException success) {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
@ -125,9 +125,7 @@ public class RecursiveActionTest extends JSR166TestCase {
assertFalse(a.cancel(true)); assertFalse(a.cancel(true));
try { try {
assertNull(a.get()); assertNull(a.get());
} catch (Throwable fail) { threadUnexpectedException(fail); } assertNull(a.get(randomTimeout(), randomTimeUnit()));
try {
assertNull(a.get(5L, SECONDS));
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
} }
@ -152,7 +150,7 @@ public class RecursiveActionTest extends JSR166TestCase {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
try { try {
a.get(5L, SECONDS); a.get(randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (CancellationException success) { } catch (CancellationException success) {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
@ -183,7 +181,7 @@ public class RecursiveActionTest extends JSR166TestCase {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
try { try {
a.get(5L, SECONDS); a.get(randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (ExecutionException success) { } catch (ExecutionException success) {
assertSame(t.getClass(), success.getCause().getClass()); assertSame(t.getClass(), success.getCause().getClass());
@ -469,7 +467,7 @@ public class RecursiveActionTest extends JSR166TestCase {
protected void realCompute() throws Exception { protected void realCompute() throws Exception {
FibAction f = new FibAction(8); FibAction f = new FibAction(8);
assertSame(f, f.fork()); assertSame(f, f.fork());
assertNull(f.get(5L, SECONDS)); assertNull(f.get(LONG_DELAY_MS, MILLISECONDS));
assertEquals(21, f.result); assertEquals(21, f.result);
checkCompletedNormally(f); checkCompletedNormally(f);
}}; }};
@ -485,7 +483,7 @@ public class RecursiveActionTest extends JSR166TestCase {
FibAction f = new FibAction(8); FibAction f = new FibAction(8);
assertSame(f, f.fork()); assertSame(f, f.fork());
try { try {
f.get(5L, null); f.get(randomTimeout(), null);
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
}}; }};
@ -604,7 +602,7 @@ public class RecursiveActionTest extends JSR166TestCase {
FailingFibAction f = new FailingFibAction(8); FailingFibAction f = new FailingFibAction(8);
assertSame(f, f.fork()); assertSame(f, f.fork());
try { try {
f.get(5L, SECONDS); f.get(LONG_DELAY_MS, MILLISECONDS);
shouldThrow(); shouldThrow();
} catch (ExecutionException success) { } catch (ExecutionException success) {
Throwable cause = success.getCause(); Throwable cause = success.getCause();
@ -696,7 +694,7 @@ public class RecursiveActionTest extends JSR166TestCase {
assertTrue(f.cancel(true)); assertTrue(f.cancel(true));
assertSame(f, f.fork()); assertSame(f, f.fork());
try { try {
f.get(5L, SECONDS); f.get(LONG_DELAY_MS, MILLISECONDS);
shouldThrow(); shouldThrow();
} catch (CancellationException success) { } catch (CancellationException success) {
checkCancelled(f); checkCancelled(f);

View File

@ -31,7 +31,7 @@
* http://creativecommons.org/publicdomain/zero/1.0/ * http://creativecommons.org/publicdomain/zero/1.0/
*/ */
import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.HashSet; import java.util.HashSet;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
@ -96,14 +96,14 @@ public class RecursiveTaskTest extends JSR166TestCase {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
try { try {
a.get(5L, SECONDS); a.get(randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (InterruptedException success) { } catch (InterruptedException success) {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
} }
try { try {
a.get(0L, SECONDS); a.get(randomExpiredTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (TimeoutException success) { } catch (TimeoutException success) {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
@ -121,9 +121,7 @@ public class RecursiveTaskTest extends JSR166TestCase {
assertFalse(a.cancel(true)); assertFalse(a.cancel(true));
try { try {
assertSame(expected, a.get()); assertSame(expected, a.get());
} catch (Throwable fail) { threadUnexpectedException(fail); } assertSame(expected, a.get(randomTimeout(), randomTimeUnit()));
try {
assertSame(expected, a.get(5L, SECONDS));
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
} }
@ -168,7 +166,7 @@ public class RecursiveTaskTest extends JSR166TestCase {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
try { try {
a.get(5L, SECONDS); a.get(randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (CancellationException success) { } catch (CancellationException success) {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
@ -199,7 +197,7 @@ public class RecursiveTaskTest extends JSR166TestCase {
} catch (Throwable fail) { threadUnexpectedException(fail); } } catch (Throwable fail) { threadUnexpectedException(fail); }
try { try {
a.get(5L, SECONDS); a.get(randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (ExecutionException success) { } catch (ExecutionException success) {
assertSame(t.getClass(), success.getCause().getClass()); assertSame(t.getClass(), success.getCause().getClass());
@ -320,7 +318,7 @@ public class RecursiveTaskTest extends JSR166TestCase {
public Integer realCompute() throws Exception { public Integer realCompute() throws Exception {
FibTask f = new FibTask(8); FibTask f = new FibTask(8);
assertSame(f, f.fork()); assertSame(f, f.fork());
Integer r = f.get(5L, SECONDS); Integer r = f.get(LONG_DELAY_MS, MILLISECONDS);
assertEquals(21, (int) r); assertEquals(21, (int) r);
checkCompletedNormally(f, r); checkCompletedNormally(f, r);
return r; return r;
@ -446,7 +444,7 @@ public class RecursiveTaskTest extends JSR166TestCase {
FailingFibTask f = new FailingFibTask(8); FailingFibTask f = new FailingFibTask(8);
assertSame(f, f.fork()); assertSame(f, f.fork());
try { try {
Integer r = f.get(5L, SECONDS); Integer r = f.get(LONG_DELAY_MS, MILLISECONDS);
shouldThrow(); shouldThrow();
} catch (ExecutionException success) { } catch (ExecutionException success) {
Throwable cause = success.getCause(); Throwable cause = success.getCause();
@ -543,7 +541,7 @@ public class RecursiveTaskTest extends JSR166TestCase {
assertTrue(f.cancel(true)); assertTrue(f.cancel(true));
assertSame(f, f.fork()); assertSame(f, f.fork());
try { try {
Integer r = f.get(5L, SECONDS); Integer r = f.get(LONG_DELAY_MS, MILLISECONDS);
shouldThrow(); shouldThrow();
} catch (CancellationException success) { } catch (CancellationException success) {
checkCancelled(f); checkCancelled(f);

View File

@ -47,6 +47,7 @@ import junit.framework.AssertionFailedError;
import junit.framework.Test; import junit.framework.Test;
import junit.framework.TestSuite; import junit.framework.TestSuite;
@SuppressWarnings("WaitNotInLoop") // we implement spurious-wakeup freedom
public class ReentrantLockTest extends JSR166TestCase { public class ReentrantLockTest extends JSR166TestCase {
public static void main(String[] args) { public static void main(String[] args) {
main(suite(), args); main(suite(), args);
@ -912,7 +913,7 @@ public class ReentrantLockTest extends JSR166TestCase {
public void testAwaitUninterruptibly_fair() { testAwaitUninterruptibly(true); } public void testAwaitUninterruptibly_fair() { testAwaitUninterruptibly(true); }
public void testAwaitUninterruptibly(boolean fair) { public void testAwaitUninterruptibly(boolean fair) {
final ReentrantLock lock = new ReentrantLock(fair); final ReentrantLock lock = new ReentrantLock(fair);
final Condition c = lock.newCondition(); final Condition condition = lock.newCondition();
final CountDownLatch pleaseInterrupt = new CountDownLatch(2); final CountDownLatch pleaseInterrupt = new CountDownLatch(2);
Thread t1 = newStartedThread(new CheckedRunnable() { Thread t1 = newStartedThread(new CheckedRunnable() {
@ -921,7 +922,7 @@ public class ReentrantLockTest extends JSR166TestCase {
lock.lock(); lock.lock();
pleaseInterrupt.countDown(); pleaseInterrupt.countDown();
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
c.awaitUninterruptibly(); condition.awaitUninterruptibly();
assertTrue(Thread.interrupted()); assertTrue(Thread.interrupted());
lock.unlock(); lock.unlock();
}}); }});
@ -931,21 +932,20 @@ public class ReentrantLockTest extends JSR166TestCase {
// Interrupt during awaitUninterruptibly // Interrupt during awaitUninterruptibly
lock.lock(); lock.lock();
pleaseInterrupt.countDown(); pleaseInterrupt.countDown();
c.awaitUninterruptibly(); condition.awaitUninterruptibly();
assertTrue(Thread.interrupted()); assertTrue(Thread.interrupted());
lock.unlock(); lock.unlock();
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
t2.interrupt();
lock.lock(); lock.lock();
lock.unlock(); lock.unlock();
t2.interrupt(); assertThreadBlocks(t1, Thread.State.WAITING);
assertThreadBlocks(t2, Thread.State.WAITING);
assertThreadStaysAlive(t1);
assertTrue(t2.isAlive());
lock.lock(); lock.lock();
c.signalAll(); condition.signalAll();
lock.unlock(); lock.unlock();
awaitTermination(t1); awaitTermination(t1);

View File

@ -48,6 +48,7 @@ import junit.framework.AssertionFailedError;
import junit.framework.Test; import junit.framework.Test;
import junit.framework.TestSuite; import junit.framework.TestSuite;
@SuppressWarnings("WaitNotInLoop") // we implement spurious-wakeup freedom
public class ReentrantReadWriteLockTest extends JSR166TestCase { public class ReentrantReadWriteLockTest extends JSR166TestCase {
public static void main(String[] args) { public static void main(String[] args) {
main(suite(), args); main(suite(), args);
@ -1036,42 +1037,41 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
public void testAwaitUninterruptibly() { testAwaitUninterruptibly(false); } public void testAwaitUninterruptibly() { testAwaitUninterruptibly(false); }
public void testAwaitUninterruptibly_fair() { testAwaitUninterruptibly(true); } public void testAwaitUninterruptibly_fair() { testAwaitUninterruptibly(true); }
public void testAwaitUninterruptibly(boolean fair) { public void testAwaitUninterruptibly(boolean fair) {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); final Lock lock = new ReentrantReadWriteLock(fair).writeLock();
final Condition c = lock.writeLock().newCondition(); final Condition condition = lock.newCondition();
final CountDownLatch pleaseInterrupt = new CountDownLatch(2); final CountDownLatch pleaseInterrupt = new CountDownLatch(2);
Thread t1 = newStartedThread(new CheckedRunnable() { Thread t1 = newStartedThread(new CheckedRunnable() {
public void realRun() { public void realRun() {
// Interrupt before awaitUninterruptibly // Interrupt before awaitUninterruptibly
lock.writeLock().lock(); lock.lock();
pleaseInterrupt.countDown(); pleaseInterrupt.countDown();
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
c.awaitUninterruptibly(); condition.awaitUninterruptibly();
assertTrue(Thread.interrupted()); assertTrue(Thread.interrupted());
lock.writeLock().unlock(); lock.unlock();
}}); }});
Thread t2 = newStartedThread(new CheckedRunnable() { Thread t2 = newStartedThread(new CheckedRunnable() {
public void realRun() { public void realRun() {
// Interrupt during awaitUninterruptibly // Interrupt during awaitUninterruptibly
lock.writeLock().lock(); lock.lock();
pleaseInterrupt.countDown(); pleaseInterrupt.countDown();
c.awaitUninterruptibly(); condition.awaitUninterruptibly();
assertTrue(Thread.interrupted()); assertTrue(Thread.interrupted());
lock.writeLock().unlock(); lock.unlock();
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
lock.writeLock().lock();
lock.writeLock().unlock();
t2.interrupt(); t2.interrupt();
lock.lock();
lock.unlock();
assertThreadBlocks(t1, Thread.State.WAITING);
assertThreadBlocks(t2, Thread.State.WAITING);
assertThreadStaysAlive(t1); lock.lock();
assertTrue(t2.isAlive()); condition.signalAll();
lock.unlock();
lock.writeLock().lock();
c.signalAll();
lock.writeLock().unlock();
awaitTermination(t1); awaitTermination(t1);
awaitTermination(t2); awaitTermination(t2);

View File

@ -36,6 +36,8 @@ import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
@ -52,12 +54,14 @@ import java.util.concurrent.RunnableScheduledFuture;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Stream;
import junit.framework.Test; import junit.framework.Test;
import junit.framework.TestSuite; import junit.framework.TestSuite;
@ -303,110 +307,67 @@ public class ScheduledExecutorSubclassTest extends JSR166TestCase {
} }
/** /**
* execute(null) throws NPE * Submitting null tasks throws NullPointerException
*/ */
public void testExecuteNull() throws InterruptedException { public void testNullTaskSubmission() {
final CustomExecutor p = new CustomExecutor(1); final CustomExecutor p = new CustomExecutor(1);
try (PoolCleaner cleaner = cleaner(p)) { try (PoolCleaner cleaner = cleaner(p)) {
try { assertNullTaskSubmissionThrowsNullPointerException(p);
p.execute(null);
shouldThrow();
} catch (NullPointerException success) {}
} }
} }
/** /**
* schedule(null) throws NPE * Submitted tasks are rejected when shutdown
*/ */
public void testScheduleNull() throws InterruptedException { public void testSubmittedTasksRejectedWhenShutdown() throws InterruptedException {
final CustomExecutor p = new CustomExecutor(1); final CustomExecutor p = new CustomExecutor(2);
try (PoolCleaner cleaner = cleaner(p)) { final ThreadLocalRandom rnd = ThreadLocalRandom.current();
final CountDownLatch threadsStarted = new CountDownLatch(p.getCorePoolSize());
final CountDownLatch done = new CountDownLatch(1);
final Runnable r = () -> {
threadsStarted.countDown();
for (;;) {
try { try {
TrackedCallable callable = null; done.await();
Future f = p.schedule(callable, SHORT_DELAY_MS, MILLISECONDS); return;
shouldThrow(); } catch (InterruptedException shutdownNowDeliberatelyIgnored) {}
} catch (NullPointerException success) {} }};
final Callable<Boolean> c = () -> {
threadsStarted.countDown();
for (;;) {
try {
done.await();
return Boolean.TRUE;
} catch (InterruptedException shutdownNowDeliberatelyIgnored) {}
}};
try (PoolCleaner cleaner = cleaner(p, done)) {
for (int i = p.getCorePoolSize(); i--> 0; ) {
switch (rnd.nextInt(4)) {
case 0: p.execute(r); break;
case 1: assertFalse(p.submit(r).isDone()); break;
case 2: assertFalse(p.submit(r, Boolean.TRUE).isDone()); break;
case 3: assertFalse(p.submit(c).isDone()); break;
} }
} }
/** // ScheduledThreadPoolExecutor has an unbounded queue, so never saturated.
* execute throws RejectedExecutionException if shutdown await(threadsStarted);
*/
public void testSchedule1_RejectedExecutionException() { if (rnd.nextBoolean())
final CustomExecutor p = new CustomExecutor(1); p.shutdownNow();
try (PoolCleaner cleaner = cleaner(p)) { else
try {
p.shutdown(); p.shutdown();
p.schedule(new NoOpRunnable(), // Pool is shutdown, but not yet terminated
MEDIUM_DELAY_MS, MILLISECONDS); assertTaskSubmissionsAreRejected(p);
shouldThrow(); assertFalse(p.isTerminated());
} catch (RejectedExecutionException success) {
} catch (SecurityException ok) {}
}
}
/** done.countDown(); // release blocking tasks
* schedule throws RejectedExecutionException if shutdown assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
*/
public void testSchedule2_RejectedExecutionException() {
final CustomExecutor p = new CustomExecutor(1);
try (PoolCleaner cleaner = cleaner(p)) {
try {
p.shutdown();
p.schedule(new NoOpCallable(),
MEDIUM_DELAY_MS, MILLISECONDS);
shouldThrow();
} catch (RejectedExecutionException success) {
} catch (SecurityException ok) {}
}
}
/** assertTaskSubmissionsAreRejected(p);
* schedule callable throws RejectedExecutionException if shutdown
*/
public void testSchedule3_RejectedExecutionException() {
final CustomExecutor p = new CustomExecutor(1);
try (PoolCleaner cleaner = cleaner(p)) {
try {
p.shutdown();
p.schedule(new NoOpCallable(),
MEDIUM_DELAY_MS, MILLISECONDS);
shouldThrow();
} catch (RejectedExecutionException success) {
} catch (SecurityException ok) {}
}
}
/**
* scheduleAtFixedRate throws RejectedExecutionException if shutdown
*/
public void testScheduleAtFixedRate1_RejectedExecutionException() {
final CustomExecutor p = new CustomExecutor(1);
try (PoolCleaner cleaner = cleaner(p)) {
try {
p.shutdown();
p.scheduleAtFixedRate(new NoOpRunnable(),
MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
shouldThrow();
} catch (RejectedExecutionException success) {
} catch (SecurityException ok) {}
}
}
/**
* scheduleWithFixedDelay throws RejectedExecutionException if shutdown
*/
public void testScheduleWithFixedDelay1_RejectedExecutionException() {
final CustomExecutor p = new CustomExecutor(1);
try (PoolCleaner cleaner = cleaner(p)) {
try {
p.shutdown();
p.scheduleWithFixedDelay(new NoOpRunnable(),
MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
shouldThrow();
} catch (RejectedExecutionException success) {
} catch (SecurityException ok) {}
} }
assertEquals(p.getCorePoolSize(), p.getCompletedTaskCount());
} }
/** /**
@ -445,13 +406,13 @@ public class ScheduledExecutorSubclassTest extends JSR166TestCase {
public void realRun() throws InterruptedException { public void realRun() throws InterruptedException {
threadStarted.countDown(); threadStarted.countDown();
assertEquals(0, p.getCompletedTaskCount()); assertEquals(0, p.getCompletedTaskCount());
threadProceed.await(); await(threadProceed);
threadDone.countDown(); threadDone.countDown();
}}); }});
await(threadStarted); await(threadStarted);
assertEquals(0, p.getCompletedTaskCount()); assertEquals(0, p.getCompletedTaskCount());
threadProceed.countDown(); threadProceed.countDown();
threadDone.await(); await(threadDone);
long startTime = System.nanoTime(); long startTime = System.nanoTime();
while (p.getCompletedTaskCount() != 1) { while (p.getCompletedTaskCount() != 1) {
if (millisElapsedSince(startTime) > LONG_DELAY_MS) if (millisElapsedSince(startTime) > LONG_DELAY_MS)
@ -812,91 +773,187 @@ public class ScheduledExecutorSubclassTest extends JSR166TestCase {
* - setExecuteExistingDelayedTasksAfterShutdownPolicy * - setExecuteExistingDelayedTasksAfterShutdownPolicy
* - setContinueExistingPeriodicTasksAfterShutdownPolicy * - setContinueExistingPeriodicTasksAfterShutdownPolicy
*/ */
@SuppressWarnings("FutureReturnValueIgnored")
public void testShutdown_cancellation() throws Exception { public void testShutdown_cancellation() throws Exception {
Boolean[] allBooleans = { null, Boolean.FALSE, Boolean.TRUE }; final int poolSize = 4;
for (Boolean policy : allBooleans)
{
final int poolSize = 2;
final CustomExecutor p = new CustomExecutor(poolSize); final CustomExecutor p = new CustomExecutor(poolSize);
final boolean effectiveDelayedPolicy = (policy != Boolean.FALSE); final BlockingQueue<Runnable> q = p.getQueue();
final boolean effectivePeriodicPolicy = (policy == Boolean.TRUE); final ThreadLocalRandom rnd = ThreadLocalRandom.current();
final boolean effectiveRemovePolicy = (policy == Boolean.TRUE); final long delay = rnd.nextInt(2);
if (policy != null) { final int rounds = rnd.nextInt(1, 3);
p.setExecuteExistingDelayedTasksAfterShutdownPolicy(policy); final boolean effectiveDelayedPolicy;
p.setContinueExistingPeriodicTasksAfterShutdownPolicy(policy); final boolean effectivePeriodicPolicy;
p.setRemoveOnCancelPolicy(policy); final boolean effectiveRemovePolicy;
}
if (rnd.nextBoolean())
p.setExecuteExistingDelayedTasksAfterShutdownPolicy(
effectiveDelayedPolicy = rnd.nextBoolean());
else
effectiveDelayedPolicy = true;
assertEquals(effectiveDelayedPolicy, assertEquals(effectiveDelayedPolicy,
p.getExecuteExistingDelayedTasksAfterShutdownPolicy()); p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
if (rnd.nextBoolean())
p.setContinueExistingPeriodicTasksAfterShutdownPolicy(
effectivePeriodicPolicy = rnd.nextBoolean());
else
effectivePeriodicPolicy = false;
assertEquals(effectivePeriodicPolicy, assertEquals(effectivePeriodicPolicy,
p.getContinueExistingPeriodicTasksAfterShutdownPolicy()); p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
if (rnd.nextBoolean())
p.setRemoveOnCancelPolicy(
effectiveRemovePolicy = rnd.nextBoolean());
else
effectiveRemovePolicy = false;
assertEquals(effectiveRemovePolicy, assertEquals(effectiveRemovePolicy,
p.getRemoveOnCancelPolicy()); p.getRemoveOnCancelPolicy());
// Strategy: Wedge the pool with poolSize "blocker" threads
final boolean periodicTasksContinue = effectivePeriodicPolicy && rnd.nextBoolean();
// Strategy: Wedge the pool with one wave of "blocker" tasks,
// then add a second wave that waits in the queue until unblocked.
final AtomicInteger ran = new AtomicInteger(0); final AtomicInteger ran = new AtomicInteger(0);
final CountDownLatch poolBlocked = new CountDownLatch(poolSize); final CountDownLatch poolBlocked = new CountDownLatch(poolSize);
final CountDownLatch unblock = new CountDownLatch(1); final CountDownLatch unblock = new CountDownLatch(1);
final CountDownLatch periodicLatch1 = new CountDownLatch(2); final RuntimeException exception = new RuntimeException();
final CountDownLatch periodicLatch2 = new CountDownLatch(2);
Runnable task = new CheckedRunnable() { public void realRun() class Task implements Runnable {
throws InterruptedException { public void run() {
poolBlocked.countDown(); try {
assertTrue(unblock.await(LONG_DELAY_MS, MILLISECONDS));
ran.getAndIncrement(); ran.getAndIncrement();
}}; poolBlocked.countDown();
List<Future<?>> blockers = new ArrayList<>(); await(unblock);
List<Future<?>> periodics = new ArrayList<>(); } catch (Throwable fail) { threadUnexpectedException(fail); }
}
}
class PeriodicTask extends Task {
PeriodicTask(int rounds) { this.rounds = rounds; }
int rounds;
public void run() {
if (--rounds == 0) super.run();
// throw exception to surely terminate this periodic task,
// but in a separate execution and in a detectable way.
if (rounds == -1) throw exception;
}
}
Runnable task = new Task();
List<Future<?>> immediates = new ArrayList<>();
List<Future<?>> delayeds = new ArrayList<>(); List<Future<?>> delayeds = new ArrayList<>();
for (int i = 0; i < poolSize; i++) List<Future<?>> periodics = new ArrayList<>();
blockers.add(p.submit(task));
assertTrue(poolBlocked.await(LONG_DELAY_MS, MILLISECONDS));
periodics.add(p.scheduleAtFixedRate(countDowner(periodicLatch1), immediates.add(p.submit(task));
1, 1, MILLISECONDS)); delayeds.add(p.schedule(task, delay, MILLISECONDS));
periodics.add(p.scheduleWithFixedDelay(countDowner(periodicLatch2), periodics.add(p.scheduleAtFixedRate(
1, 1, MILLISECONDS)); new PeriodicTask(rounds), delay, 1, MILLISECONDS));
delayeds.add(p.schedule(task, 1, MILLISECONDS)); periodics.add(p.scheduleWithFixedDelay(
new PeriodicTask(rounds), delay, 1, MILLISECONDS));
await(poolBlocked);
assertEquals(poolSize, ran.get());
assertEquals(poolSize, p.getActiveCount());
assertTrue(q.isEmpty());
// Add second wave of tasks.
immediates.add(p.submit(task));
delayeds.add(p.schedule(task, effectiveDelayedPolicy ? delay : LONG_DELAY_MS, MILLISECONDS));
periodics.add(p.scheduleAtFixedRate(
new PeriodicTask(rounds), delay, 1, MILLISECONDS));
periodics.add(p.scheduleWithFixedDelay(
new PeriodicTask(rounds), delay, 1, MILLISECONDS));
assertEquals(poolSize, q.size());
assertEquals(poolSize, ran.get());
immediates.forEach(
f -> assertTrue(((ScheduledFuture)f).getDelay(NANOSECONDS) <= 0L));
Stream.of(immediates, delayeds, periodics).flatMap(c -> c.stream())
.forEach(f -> assertFalse(f.isDone()));
assertTrue(p.getQueue().containsAll(periodics));
assertTrue(p.getQueue().containsAll(delayeds));
try { p.shutdown(); } catch (SecurityException ok) { return; } try { p.shutdown(); } catch (SecurityException ok) { return; }
assertTrue(p.isShutdown()); assertTrue(p.isShutdown());
assertTrue(p.isTerminating());
assertFalse(p.isTerminated()); assertFalse(p.isTerminated());
for (Future<?> periodic : periodics) {
assertTrue(effectivePeriodicPolicy ^ periodic.isCancelled());
assertTrue(effectivePeriodicPolicy ^ periodic.isDone());
}
for (Future<?> delayed : delayeds) {
assertTrue(effectiveDelayedPolicy ^ delayed.isCancelled());
assertTrue(effectiveDelayedPolicy ^ delayed.isDone());
}
if (testImplementationDetails) {
assertEquals(effectivePeriodicPolicy,
p.getQueue().containsAll(periodics));
assertEquals(effectiveDelayedPolicy,
p.getQueue().containsAll(delayeds));
}
// Release all pool threads
unblock.countDown();
for (Future<?> delayed : delayeds) { if (rnd.nextBoolean())
if (effectiveDelayedPolicy) { assertThrows(
assertNull(delayed.get()); RejectedExecutionException.class,
} () -> p.submit(task),
} () -> p.schedule(task, 1, SECONDS),
if (effectivePeriodicPolicy) { () -> p.scheduleAtFixedRate(
assertTrue(periodicLatch1.await(LONG_DELAY_MS, MILLISECONDS)); new PeriodicTask(1), 1, 1, SECONDS),
assertTrue(periodicLatch2.await(LONG_DELAY_MS, MILLISECONDS)); () -> p.scheduleWithFixedDelay(
for (Future<?> periodic : periodics) { new PeriodicTask(2), 1, 1, SECONDS));
assertTrue(periodic.cancel(false));
assertTrue(periodic.isCancelled()); assertTrue(q.contains(immediates.get(1)));
assertTrue(periodic.isDone()); assertTrue(!effectiveDelayedPolicy
^ q.contains(delayeds.get(1)));
assertTrue(!effectivePeriodicPolicy
^ q.containsAll(periodics.subList(2, 4)));
immediates.forEach(f -> assertFalse(f.isDone()));
assertFalse(delayeds.get(0).isDone());
if (effectiveDelayedPolicy)
assertFalse(delayeds.get(1).isDone());
else
assertTrue(delayeds.get(1).isCancelled());
if (effectivePeriodicPolicy)
periodics.forEach(
f -> {
assertFalse(f.isDone());
if (!periodicTasksContinue) {
assertTrue(f.cancel(false));
assertTrue(f.isCancelled());
} }
});
else {
periodics.subList(0, 2).forEach(f -> assertFalse(f.isDone()));
periodics.subList(2, 4).forEach(f -> assertTrue(f.isCancelled()));
} }
unblock.countDown(); // Release all pool threads
assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
assertFalse(p.isTerminating());
assertTrue(p.isTerminated()); assertTrue(p.isTerminated());
assertEquals(2 + (effectiveDelayedPolicy ? 1 : 0), ran.get());
}} assertTrue(q.isEmpty());
Stream.of(immediates, delayeds, periodics).flatMap(c -> c.stream())
.forEach(f -> assertTrue(f.isDone()));
for (Future<?> f : immediates) assertNull(f.get());
assertNull(delayeds.get(0).get());
if (effectiveDelayedPolicy)
assertNull(delayeds.get(1).get());
else
assertTrue(delayeds.get(1).isCancelled());
if (periodicTasksContinue)
periodics.forEach(
f -> {
try { f.get(); }
catch (ExecutionException success) {
assertSame(exception, success.getCause());
}
catch (Throwable fail) { threadUnexpectedException(fail); }
});
else
periodics.forEach(f -> assertTrue(f.isCancelled()));
assertEquals(poolSize + 1
+ (effectiveDelayedPolicy ? 1 : 0)
+ (periodicTasksContinue ? 2 : 0),
ran.get());
}
/** /**
* completed submit of callable returns result * completed submit of callable returns result
@ -948,7 +1005,7 @@ public class ScheduledExecutorSubclassTest extends JSR166TestCase {
} }
/** /**
* invokeAny(empty collection) throws IAE * invokeAny(empty collection) throws IllegalArgumentException
*/ */
public void testInvokeAny2() throws Exception { public void testInvokeAny2() throws Exception {
final ExecutorService e = new CustomExecutor(2); final ExecutorService e = new CustomExecutor(2);
@ -1023,12 +1080,14 @@ public class ScheduledExecutorSubclassTest extends JSR166TestCase {
} }
/** /**
* invokeAll(empty collection) returns empty collection * invokeAll(empty collection) returns empty list
*/ */
public void testInvokeAll2() throws Exception { public void testInvokeAll2() throws Exception {
final ExecutorService e = new CustomExecutor(2); final ExecutorService e = new CustomExecutor(2);
final Collection<Callable<String>> emptyCollection
= Collections.emptyList();
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>()); List<Future<String>> r = e.invokeAll(emptyCollection);
assertTrue(r.isEmpty()); assertTrue(r.isEmpty());
} }
} }
@ -1091,7 +1150,7 @@ public class ScheduledExecutorSubclassTest extends JSR166TestCase {
final ExecutorService e = new CustomExecutor(2); final ExecutorService e = new CustomExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
try { try {
e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAny(null, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
@ -1106,20 +1165,22 @@ public class ScheduledExecutorSubclassTest extends JSR166TestCase {
List<Callable<String>> l = new ArrayList<>(); List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask()); l.add(new StringTask());
try { try {
e.invokeAny(l, MEDIUM_DELAY_MS, null); e.invokeAny(l, randomTimeout(), null);
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
} }
/** /**
* timed invokeAny(empty collection) throws IAE * timed invokeAny(empty collection) throws IllegalArgumentException
*/ */
public void testTimedInvokeAny2() throws Exception { public void testTimedInvokeAny2() throws Exception {
final ExecutorService e = new CustomExecutor(2); final ExecutorService e = new CustomExecutor(2);
final Collection<Callable<String>> emptyCollection
= Collections.emptyList();
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
try { try {
e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAny(emptyCollection, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (IllegalArgumentException success) {} } catch (IllegalArgumentException success) {}
} }
@ -1136,7 +1197,7 @@ public class ScheduledExecutorSubclassTest extends JSR166TestCase {
l.add(latchAwaitingStringTask(latch)); l.add(latchAwaitingStringTask(latch));
l.add(null); l.add(null);
try { try {
e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAny(l, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
latch.countDown(); latch.countDown();
@ -1179,20 +1240,20 @@ public class ScheduledExecutorSubclassTest extends JSR166TestCase {
} }
/** /**
* timed invokeAll(null) throws NPE * timed invokeAll(null) throws NullPointerException
*/ */
public void testTimedInvokeAll1() throws Exception { public void testTimedInvokeAll1() throws Exception {
final ExecutorService e = new CustomExecutor(2); final ExecutorService e = new CustomExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
try { try {
e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAll(null, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
} }
/** /**
* timed invokeAll(,,null) throws NPE * timed invokeAll(,,null) throws NullPointerException
*/ */
public void testTimedInvokeAllNullTimeUnit() throws Exception { public void testTimedInvokeAllNullTimeUnit() throws Exception {
final ExecutorService e = new CustomExecutor(2); final ExecutorService e = new CustomExecutor(2);
@ -1200,19 +1261,22 @@ public class ScheduledExecutorSubclassTest extends JSR166TestCase {
List<Callable<String>> l = new ArrayList<>(); List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask()); l.add(new StringTask());
try { try {
e.invokeAll(l, MEDIUM_DELAY_MS, null); e.invokeAll(l, randomTimeout(), null);
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
} }
/** /**
* timed invokeAll(empty collection) returns empty collection * timed invokeAll(empty collection) returns empty list
*/ */
public void testTimedInvokeAll2() throws Exception { public void testTimedInvokeAll2() throws Exception {
final ExecutorService e = new CustomExecutor(2); final ExecutorService e = new CustomExecutor(2);
final Collection<Callable<String>> emptyCollection
= Collections.emptyList();
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS); List<Future<String>> r =
e.invokeAll(emptyCollection, randomTimeout(), randomTimeUnit());
assertTrue(r.isEmpty()); assertTrue(r.isEmpty());
} }
} }
@ -1227,7 +1291,7 @@ public class ScheduledExecutorSubclassTest extends JSR166TestCase {
l.add(new StringTask()); l.add(new StringTask());
l.add(null); l.add(null);
try { try {
e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAll(l, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
@ -1238,11 +1302,11 @@ public class ScheduledExecutorSubclassTest extends JSR166TestCase {
*/ */
public void testTimedInvokeAll4() throws Exception { public void testTimedInvokeAll4() throws Exception {
final ExecutorService e = new CustomExecutor(2); final ExecutorService e = new CustomExecutor(2);
final Collection<Callable<String>> c = new ArrayList<>();
c.add(new NPETask());
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
List<Future<String>> futures = List<Future<String>> futures =
e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAll(c, LONG_DELAY_MS, MILLISECONDS);
assertEquals(1, futures.size()); assertEquals(1, futures.size());
try { try {
futures.get(0).get(); futures.get(0).get();

View File

@ -38,6 +38,8 @@ import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
@ -51,10 +53,12 @@ import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Stream;
import junit.framework.Test; import junit.framework.Test;
import junit.framework.TestSuite; import junit.framework.TestSuite;
@ -77,7 +81,7 @@ public class ScheduledExecutorTest extends JSR166TestCase {
final Runnable task = new CheckedRunnable() { final Runnable task = new CheckedRunnable() {
public void realRun() { done.countDown(); }}; public void realRun() { done.countDown(); }};
p.execute(task); p.execute(task);
assertTrue(done.await(LONG_DELAY_MS, MILLISECONDS)); await(done);
} }
} }
@ -98,7 +102,7 @@ public class ScheduledExecutorTest extends JSR166TestCase {
Future f = p.schedule(task, timeoutMillis(), MILLISECONDS); Future f = p.schedule(task, timeoutMillis(), MILLISECONDS);
assertSame(Boolean.TRUE, f.get()); assertSame(Boolean.TRUE, f.get());
assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
assertTrue(done.await(0L, MILLISECONDS)); assertEquals(0L, done.getCount());
} }
} }
@ -247,110 +251,67 @@ public class ScheduledExecutorTest extends JSR166TestCase {
} }
/** /**
* execute(null) throws NPE * Submitting null tasks throws NullPointerException
*/ */
public void testExecuteNull() throws InterruptedException { public void testNullTaskSubmission() {
final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
try (PoolCleaner cleaner = cleaner(p)) { try (PoolCleaner cleaner = cleaner(p)) {
try { assertNullTaskSubmissionThrowsNullPointerException(p);
p.execute(null);
shouldThrow();
} catch (NullPointerException success) {}
} }
} }
/** /**
* schedule(null) throws NPE * Submitted tasks are rejected when shutdown
*/ */
public void testScheduleNull() throws InterruptedException { public void testSubmittedTasksRejectedWhenShutdown() throws InterruptedException {
final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
try (PoolCleaner cleaner = cleaner(p)) { final ThreadLocalRandom rnd = ThreadLocalRandom.current();
final CountDownLatch threadsStarted = new CountDownLatch(p.getCorePoolSize());
final CountDownLatch done = new CountDownLatch(1);
final Runnable r = () -> {
threadsStarted.countDown();
for (;;) {
try { try {
TrackedCallable callable = null; done.await();
Future f = p.schedule(callable, SHORT_DELAY_MS, MILLISECONDS); return;
shouldThrow(); } catch (InterruptedException shutdownNowDeliberatelyIgnored) {}
} catch (NullPointerException success) {} }};
final Callable<Boolean> c = () -> {
threadsStarted.countDown();
for (;;) {
try {
done.await();
return Boolean.TRUE;
} catch (InterruptedException shutdownNowDeliberatelyIgnored) {}
}};
try (PoolCleaner cleaner = cleaner(p, done)) {
for (int i = p.getCorePoolSize(); i--> 0; ) {
switch (rnd.nextInt(4)) {
case 0: p.execute(r); break;
case 1: assertFalse(p.submit(r).isDone()); break;
case 2: assertFalse(p.submit(r, Boolean.TRUE).isDone()); break;
case 3: assertFalse(p.submit(c).isDone()); break;
} }
} }
/** // ScheduledThreadPoolExecutor has an unbounded queue, so never saturated.
* execute throws RejectedExecutionException if shutdown await(threadsStarted);
*/
public void testSchedule1_RejectedExecutionException() throws InterruptedException { if (rnd.nextBoolean())
final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); p.shutdownNow();
try (PoolCleaner cleaner = cleaner(p)) { else
try {
p.shutdown(); p.shutdown();
p.schedule(new NoOpRunnable(), // Pool is shutdown, but not yet terminated
MEDIUM_DELAY_MS, MILLISECONDS); assertTaskSubmissionsAreRejected(p);
shouldThrow(); assertFalse(p.isTerminated());
} catch (RejectedExecutionException success) {
} catch (SecurityException ok) {}
}
}
/** done.countDown(); // release blocking tasks
* schedule throws RejectedExecutionException if shutdown assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
*/
public void testSchedule2_RejectedExecutionException() throws InterruptedException {
final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
try (PoolCleaner cleaner = cleaner(p)) {
try {
p.shutdown();
p.schedule(new NoOpCallable(),
MEDIUM_DELAY_MS, MILLISECONDS);
shouldThrow();
} catch (RejectedExecutionException success) {
} catch (SecurityException ok) {}
}
}
/** assertTaskSubmissionsAreRejected(p);
* schedule callable throws RejectedExecutionException if shutdown
*/
public void testSchedule3_RejectedExecutionException() throws InterruptedException {
final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
try (PoolCleaner cleaner = cleaner(p)) {
try {
p.shutdown();
p.schedule(new NoOpCallable(),
MEDIUM_DELAY_MS, MILLISECONDS);
shouldThrow();
} catch (RejectedExecutionException success) {
} catch (SecurityException ok) {}
}
}
/**
* scheduleAtFixedRate throws RejectedExecutionException if shutdown
*/
public void testScheduleAtFixedRate1_RejectedExecutionException() throws InterruptedException {
final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
try (PoolCleaner cleaner = cleaner(p)) {
try {
p.shutdown();
p.scheduleAtFixedRate(new NoOpRunnable(),
MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
shouldThrow();
} catch (RejectedExecutionException success) {
} catch (SecurityException ok) {}
}
}
/**
* scheduleWithFixedDelay throws RejectedExecutionException if shutdown
*/
public void testScheduleWithFixedDelay1_RejectedExecutionException() throws InterruptedException {
final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
try (PoolCleaner cleaner = cleaner(p)) {
try {
p.shutdown();
p.scheduleWithFixedDelay(new NoOpRunnable(),
MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
shouldThrow();
} catch (RejectedExecutionException success) {
} catch (SecurityException ok) {}
} }
assertEquals(p.getCorePoolSize(), p.getCompletedTaskCount());
} }
/** /**
@ -389,13 +350,13 @@ public class ScheduledExecutorTest extends JSR166TestCase {
public void realRun() throws InterruptedException { public void realRun() throws InterruptedException {
threadStarted.countDown(); threadStarted.countDown();
assertEquals(0, p.getCompletedTaskCount()); assertEquals(0, p.getCompletedTaskCount());
threadProceed.await(); await(threadProceed);
threadDone.countDown(); threadDone.countDown();
}}); }});
await(threadStarted); await(threadStarted);
assertEquals(0, p.getCompletedTaskCount()); assertEquals(0, p.getCompletedTaskCount());
threadProceed.countDown(); threadProceed.countDown();
threadDone.await(); await(threadDone);
long startTime = System.nanoTime(); long startTime = System.nanoTime();
while (p.getCompletedTaskCount() != 1) { while (p.getCompletedTaskCount() != 1) {
if (millisElapsedSince(startTime) > LONG_DELAY_MS) if (millisElapsedSince(startTime) > LONG_DELAY_MS)
@ -533,6 +494,17 @@ public class ScheduledExecutorTest extends JSR166TestCase {
} }
} }
/**
* The default rejected execution handler is AbortPolicy.
*/
public void testDefaultRejectedExecutionHandler() {
final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
try (PoolCleaner cleaner = cleaner(p)) {
assertTrue(p.getRejectedExecutionHandler()
instanceof ThreadPoolExecutor.AbortPolicy);
}
}
/** /**
* isShutdown is false before shutdown, true after * isShutdown is false before shutdown, true after
*/ */
@ -759,92 +731,188 @@ public class ScheduledExecutorTest extends JSR166TestCase {
* - setExecuteExistingDelayedTasksAfterShutdownPolicy * - setExecuteExistingDelayedTasksAfterShutdownPolicy
* - setContinueExistingPeriodicTasksAfterShutdownPolicy * - setContinueExistingPeriodicTasksAfterShutdownPolicy
*/ */
@SuppressWarnings("FutureReturnValueIgnored")
public void testShutdown_cancellation() throws Exception { public void testShutdown_cancellation() throws Exception {
Boolean[] allBooleans = { null, Boolean.FALSE, Boolean.TRUE }; final int poolSize = 4;
for (Boolean policy : allBooleans)
{
final int poolSize = 2;
final ScheduledThreadPoolExecutor p final ScheduledThreadPoolExecutor p
= new ScheduledThreadPoolExecutor(poolSize); = new ScheduledThreadPoolExecutor(poolSize);
final boolean effectiveDelayedPolicy = (policy != Boolean.FALSE); final BlockingQueue<Runnable> q = p.getQueue();
final boolean effectivePeriodicPolicy = (policy == Boolean.TRUE); final ThreadLocalRandom rnd = ThreadLocalRandom.current();
final boolean effectiveRemovePolicy = (policy == Boolean.TRUE); final long delay = rnd.nextInt(2);
if (policy != null) { final int rounds = rnd.nextInt(1, 3);
p.setExecuteExistingDelayedTasksAfterShutdownPolicy(policy); final boolean effectiveDelayedPolicy;
p.setContinueExistingPeriodicTasksAfterShutdownPolicy(policy); final boolean effectivePeriodicPolicy;
p.setRemoveOnCancelPolicy(policy); final boolean effectiveRemovePolicy;
}
if (rnd.nextBoolean())
p.setExecuteExistingDelayedTasksAfterShutdownPolicy(
effectiveDelayedPolicy = rnd.nextBoolean());
else
effectiveDelayedPolicy = true;
assertEquals(effectiveDelayedPolicy, assertEquals(effectiveDelayedPolicy,
p.getExecuteExistingDelayedTasksAfterShutdownPolicy()); p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
if (rnd.nextBoolean())
p.setContinueExistingPeriodicTasksAfterShutdownPolicy(
effectivePeriodicPolicy = rnd.nextBoolean());
else
effectivePeriodicPolicy = false;
assertEquals(effectivePeriodicPolicy, assertEquals(effectivePeriodicPolicy,
p.getContinueExistingPeriodicTasksAfterShutdownPolicy()); p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
if (rnd.nextBoolean())
p.setRemoveOnCancelPolicy(
effectiveRemovePolicy = rnd.nextBoolean());
else
effectiveRemovePolicy = false;
assertEquals(effectiveRemovePolicy, assertEquals(effectiveRemovePolicy,
p.getRemoveOnCancelPolicy()); p.getRemoveOnCancelPolicy());
// Strategy: Wedge the pool with poolSize "blocker" threads
final boolean periodicTasksContinue = effectivePeriodicPolicy && rnd.nextBoolean();
// Strategy: Wedge the pool with one wave of "blocker" tasks,
// then add a second wave that waits in the queue until unblocked.
final AtomicInteger ran = new AtomicInteger(0); final AtomicInteger ran = new AtomicInteger(0);
final CountDownLatch poolBlocked = new CountDownLatch(poolSize); final CountDownLatch poolBlocked = new CountDownLatch(poolSize);
final CountDownLatch unblock = new CountDownLatch(1); final CountDownLatch unblock = new CountDownLatch(1);
final CountDownLatch periodicLatch1 = new CountDownLatch(2); final RuntimeException exception = new RuntimeException();
final CountDownLatch periodicLatch2 = new CountDownLatch(2);
Runnable task = new CheckedRunnable() { public void realRun() class Task implements Runnable {
throws InterruptedException { public void run() {
poolBlocked.countDown(); try {
assertTrue(unblock.await(LONG_DELAY_MS, MILLISECONDS));
ran.getAndIncrement(); ran.getAndIncrement();
}}; poolBlocked.countDown();
List<Future<?>> blockers = new ArrayList<>(); await(unblock);
List<Future<?>> periodics = new ArrayList<>(); } catch (Throwable fail) { threadUnexpectedException(fail); }
}
}
class PeriodicTask extends Task {
PeriodicTask(int rounds) { this.rounds = rounds; }
int rounds;
public void run() {
if (--rounds == 0) super.run();
// throw exception to surely terminate this periodic task,
// but in a separate execution and in a detectable way.
if (rounds == -1) throw exception;
}
}
Runnable task = new Task();
List<Future<?>> immediates = new ArrayList<>();
List<Future<?>> delayeds = new ArrayList<>(); List<Future<?>> delayeds = new ArrayList<>();
for (int i = 0; i < poolSize; i++) List<Future<?>> periodics = new ArrayList<>();
blockers.add(p.submit(task));
assertTrue(poolBlocked.await(LONG_DELAY_MS, MILLISECONDS));
periodics.add(p.scheduleAtFixedRate(countDowner(periodicLatch1), immediates.add(p.submit(task));
1, 1, MILLISECONDS)); delayeds.add(p.schedule(task, delay, MILLISECONDS));
periodics.add(p.scheduleWithFixedDelay(countDowner(periodicLatch2), periodics.add(p.scheduleAtFixedRate(
1, 1, MILLISECONDS)); new PeriodicTask(rounds), delay, 1, MILLISECONDS));
delayeds.add(p.schedule(task, 1, MILLISECONDS)); periodics.add(p.scheduleWithFixedDelay(
new PeriodicTask(rounds), delay, 1, MILLISECONDS));
await(poolBlocked);
assertEquals(poolSize, ran.get());
assertEquals(poolSize, p.getActiveCount());
assertTrue(q.isEmpty());
// Add second wave of tasks.
immediates.add(p.submit(task));
delayeds.add(p.schedule(task, effectiveDelayedPolicy ? delay : LONG_DELAY_MS, MILLISECONDS));
periodics.add(p.scheduleAtFixedRate(
new PeriodicTask(rounds), delay, 1, MILLISECONDS));
periodics.add(p.scheduleWithFixedDelay(
new PeriodicTask(rounds), delay, 1, MILLISECONDS));
assertEquals(poolSize, q.size());
assertEquals(poolSize, ran.get());
immediates.forEach(
f -> assertTrue(((ScheduledFuture)f).getDelay(NANOSECONDS) <= 0L));
Stream.of(immediates, delayeds, periodics).flatMap(c -> c.stream())
.forEach(f -> assertFalse(f.isDone()));
assertTrue(p.getQueue().containsAll(periodics));
assertTrue(p.getQueue().containsAll(delayeds));
try { p.shutdown(); } catch (SecurityException ok) { return; } try { p.shutdown(); } catch (SecurityException ok) { return; }
assertTrue(p.isShutdown()); assertTrue(p.isShutdown());
assertTrue(p.isTerminating());
assertFalse(p.isTerminated()); assertFalse(p.isTerminated());
for (Future<?> periodic : periodics) {
assertTrue(effectivePeriodicPolicy ^ periodic.isCancelled());
assertTrue(effectivePeriodicPolicy ^ periodic.isDone());
}
for (Future<?> delayed : delayeds) {
assertTrue(effectiveDelayedPolicy ^ delayed.isCancelled());
assertTrue(effectiveDelayedPolicy ^ delayed.isDone());
}
if (testImplementationDetails) {
assertEquals(effectivePeriodicPolicy,
p.getQueue().containsAll(periodics));
assertEquals(effectiveDelayedPolicy,
p.getQueue().containsAll(delayeds));
}
// Release all pool threads
unblock.countDown();
for (Future<?> delayed : delayeds) { if (rnd.nextBoolean())
if (effectiveDelayedPolicy) { assertThrows(
assertNull(delayed.get()); RejectedExecutionException.class,
} () -> p.submit(task),
} () -> p.schedule(task, 1, SECONDS),
if (effectivePeriodicPolicy) { () -> p.scheduleAtFixedRate(
assertTrue(periodicLatch1.await(LONG_DELAY_MS, MILLISECONDS)); new PeriodicTask(1), 1, 1, SECONDS),
assertTrue(periodicLatch2.await(LONG_DELAY_MS, MILLISECONDS)); () -> p.scheduleWithFixedDelay(
for (Future<?> periodic : periodics) { new PeriodicTask(2), 1, 1, SECONDS));
assertTrue(periodic.cancel(false));
assertTrue(periodic.isCancelled()); assertTrue(q.contains(immediates.get(1)));
assertTrue(periodic.isDone()); assertTrue(!effectiveDelayedPolicy
^ q.contains(delayeds.get(1)));
assertTrue(!effectivePeriodicPolicy
^ q.containsAll(periodics.subList(2, 4)));
immediates.forEach(f -> assertFalse(f.isDone()));
assertFalse(delayeds.get(0).isDone());
if (effectiveDelayedPolicy)
assertFalse(delayeds.get(1).isDone());
else
assertTrue(delayeds.get(1).isCancelled());
if (effectivePeriodicPolicy)
periodics.forEach(
f -> {
assertFalse(f.isDone());
if (!periodicTasksContinue) {
assertTrue(f.cancel(false));
assertTrue(f.isCancelled());
} }
});
else {
periodics.subList(0, 2).forEach(f -> assertFalse(f.isDone()));
periodics.subList(2, 4).forEach(f -> assertTrue(f.isCancelled()));
} }
unblock.countDown(); // Release all pool threads
assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
assertFalse(p.isTerminating());
assertTrue(p.isTerminated()); assertTrue(p.isTerminated());
assertEquals(2 + (effectiveDelayedPolicy ? 1 : 0), ran.get());
}} assertTrue(q.isEmpty());
Stream.of(immediates, delayeds, periodics).flatMap(c -> c.stream())
.forEach(f -> assertTrue(f.isDone()));
for (Future<?> f : immediates) assertNull(f.get());
assertNull(delayeds.get(0).get());
if (effectiveDelayedPolicy)
assertNull(delayeds.get(1).get());
else
assertTrue(delayeds.get(1).isCancelled());
if (periodicTasksContinue)
periodics.forEach(
f -> {
try { f.get(); }
catch (ExecutionException success) {
assertSame(exception, success.getCause());
}
catch (Throwable fail) { threadUnexpectedException(fail); }
});
else
periodics.forEach(f -> assertTrue(f.isCancelled()));
assertEquals(poolSize + 1
+ (effectiveDelayedPolicy ? 1 : 0)
+ (periodicTasksContinue ? 2 : 0),
ran.get());
}
/** /**
* completed submit of callable returns result * completed submit of callable returns result
@ -883,7 +951,7 @@ public class ScheduledExecutorTest extends JSR166TestCase {
} }
/** /**
* invokeAny(null) throws NPE * invokeAny(null) throws NullPointerException
*/ */
public void testInvokeAny1() throws Exception { public void testInvokeAny1() throws Exception {
final ExecutorService e = new ScheduledThreadPoolExecutor(2); final ExecutorService e = new ScheduledThreadPoolExecutor(2);
@ -896,7 +964,7 @@ public class ScheduledExecutorTest extends JSR166TestCase {
} }
/** /**
* invokeAny(empty collection) throws IAE * invokeAny(empty collection) throws IllegalArgumentException
*/ */
public void testInvokeAny2() throws Exception { public void testInvokeAny2() throws Exception {
final ExecutorService e = new ScheduledThreadPoolExecutor(2); final ExecutorService e = new ScheduledThreadPoolExecutor(2);
@ -909,7 +977,7 @@ public class ScheduledExecutorTest extends JSR166TestCase {
} }
/** /**
* invokeAny(c) throws NPE if c has null elements * invokeAny(c) throws NullPointerException if c has null elements
*/ */
public void testInvokeAny3() throws Exception { public void testInvokeAny3() throws Exception {
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
@ -971,12 +1039,14 @@ public class ScheduledExecutorTest extends JSR166TestCase {
} }
/** /**
* invokeAll(empty collection) returns empty collection * invokeAll(empty collection) returns empty list
*/ */
public void testInvokeAll2() throws Exception { public void testInvokeAll2() throws Exception {
final ExecutorService e = new ScheduledThreadPoolExecutor(2); final ExecutorService e = new ScheduledThreadPoolExecutor(2);
final Collection<Callable<String>> emptyCollection
= Collections.emptyList();
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>()); List<Future<String>> r = e.invokeAll(emptyCollection);
assertTrue(r.isEmpty()); assertTrue(r.isEmpty());
} }
} }
@ -1039,14 +1109,14 @@ public class ScheduledExecutorTest extends JSR166TestCase {
final ExecutorService e = new ScheduledThreadPoolExecutor(2); final ExecutorService e = new ScheduledThreadPoolExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
try { try {
e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAny(null, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
} }
/** /**
* timed invokeAny(,,null) throws NPE * timed invokeAny(,,null) throws NullPointerException
*/ */
public void testTimedInvokeAnyNullTimeUnit() throws Exception { public void testTimedInvokeAnyNullTimeUnit() throws Exception {
final ExecutorService e = new ScheduledThreadPoolExecutor(2); final ExecutorService e = new ScheduledThreadPoolExecutor(2);
@ -1054,20 +1124,22 @@ public class ScheduledExecutorTest extends JSR166TestCase {
List<Callable<String>> l = new ArrayList<>(); List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask()); l.add(new StringTask());
try { try {
e.invokeAny(l, MEDIUM_DELAY_MS, null); e.invokeAny(l, randomTimeout(), null);
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
} }
/** /**
* timed invokeAny(empty collection) throws IAE * timed invokeAny(empty collection) throws IllegalArgumentException
*/ */
public void testTimedInvokeAny2() throws Exception { public void testTimedInvokeAny2() throws Exception {
final ExecutorService e = new ScheduledThreadPoolExecutor(2); final ExecutorService e = new ScheduledThreadPoolExecutor(2);
final Collection<Callable<String>> emptyCollection
= Collections.emptyList();
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
try { try {
e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAny(emptyCollection, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (IllegalArgumentException success) {} } catch (IllegalArgumentException success) {}
} }
@ -1084,7 +1156,7 @@ public class ScheduledExecutorTest extends JSR166TestCase {
l.add(latchAwaitingStringTask(latch)); l.add(latchAwaitingStringTask(latch));
l.add(null); l.add(null);
try { try {
e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAny(l, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
latch.countDown(); latch.countDown();
@ -1133,7 +1205,7 @@ public class ScheduledExecutorTest extends JSR166TestCase {
final ExecutorService e = new ScheduledThreadPoolExecutor(2); final ExecutorService e = new ScheduledThreadPoolExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
try { try {
e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAll(null, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
@ -1148,20 +1220,22 @@ public class ScheduledExecutorTest extends JSR166TestCase {
List<Callable<String>> l = new ArrayList<>(); List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask()); l.add(new StringTask());
try { try {
e.invokeAll(l, MEDIUM_DELAY_MS, null); e.invokeAll(l, randomTimeout(), null);
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
} }
/** /**
* timed invokeAll(empty collection) returns empty collection * timed invokeAll(empty collection) returns empty list
*/ */
public void testTimedInvokeAll2() throws Exception { public void testTimedInvokeAll2() throws Exception {
final ExecutorService e = new ScheduledThreadPoolExecutor(2); final ExecutorService e = new ScheduledThreadPoolExecutor(2);
final Collection<Callable<String>> emptyCollection
= Collections.emptyList();
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), List<Future<String>> r =
MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAll(emptyCollection, randomTimeout(), randomTimeUnit());
assertTrue(r.isEmpty()); assertTrue(r.isEmpty());
} }
} }
@ -1176,7 +1250,7 @@ public class ScheduledExecutorTest extends JSR166TestCase {
l.add(new StringTask()); l.add(new StringTask());
l.add(null); l.add(null);
try { try {
e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAll(l, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
@ -1262,18 +1336,16 @@ public class ScheduledExecutorTest extends JSR166TestCase {
* one-shot task from executing. * one-shot task from executing.
* https://bugs.openjdk.java.net/browse/JDK-8051859 * https://bugs.openjdk.java.net/browse/JDK-8051859
*/ */
@SuppressWarnings("FutureReturnValueIgnored")
public void testScheduleWithFixedDelay_overflow() throws Exception { public void testScheduleWithFixedDelay_overflow() throws Exception {
final CountDownLatch delayedDone = new CountDownLatch(1); final CountDownLatch delayedDone = new CountDownLatch(1);
final CountDownLatch immediateDone = new CountDownLatch(1); final CountDownLatch immediateDone = new CountDownLatch(1);
final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
try (PoolCleaner cleaner = cleaner(p)) { try (PoolCleaner cleaner = cleaner(p)) {
final Runnable immediate = new Runnable() { public void run() { final Runnable delayed = () -> {
immediateDone.countDown();
}};
final Runnable delayed = new Runnable() { public void run() {
delayedDone.countDown(); delayedDone.countDown();
p.submit(immediate); p.submit(() -> immediateDone.countDown());
}}; };
p.scheduleWithFixedDelay(delayed, 0L, Long.MAX_VALUE, SECONDS); p.scheduleWithFixedDelay(delayed, 0L, Long.MAX_VALUE, SECONDS);
await(delayedDone); await(delayedDone);
await(immediateDone); await(immediateDone);

View File

@ -38,6 +38,7 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.Collection; import java.util.Collection;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore; import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadLocalRandom;
import junit.framework.AssertionFailedError; import junit.framework.AssertionFailedError;
import junit.framework.Test; import junit.framework.Test;
@ -154,11 +155,13 @@ public class SemaphoreTest extends JSR166TestCase {
void acquire(Semaphore s) throws InterruptedException { void acquire(Semaphore s) throws InterruptedException {
assertTrue(s.tryAcquire(2 * LONG_DELAY_MS, MILLISECONDS)); assertTrue(s.tryAcquire(2 * LONG_DELAY_MS, MILLISECONDS));
} }
Thread.State parkedState() { return Thread.State.TIMED_WAITING; }
}, },
tryAcquireTimedN { tryAcquireTimedN {
void acquire(Semaphore s, int permits) throws InterruptedException { void acquire(Semaphore s, int permits) throws InterruptedException {
assertTrue(s.tryAcquire(permits, 2 * LONG_DELAY_MS, MILLISECONDS)); assertTrue(s.tryAcquire(permits, 2 * LONG_DELAY_MS, MILLISECONDS));
} }
Thread.State parkedState() { return Thread.State.TIMED_WAITING; }
}; };
// Intentionally meta-circular // Intentionally meta-circular
@ -172,6 +175,7 @@ public class SemaphoreTest extends JSR166TestCase {
for (int i = 0; i < permits; i++) for (int i = 0; i < permits; i++)
acquire(s); acquire(s);
} }
Thread.State parkedState() { return Thread.State.WAITING; }
} }
/** /**
@ -217,11 +221,10 @@ public class SemaphoreTest extends JSR166TestCase {
/** /**
* timed tryAcquire times out * timed tryAcquire times out
*/ */
public void testTryAcquire_timeout() { testTryAcquire_timeout(false); } public void testTryAcquire_timeout() {
public void testTryAcquire_timeout_fair() { testTryAcquire_timeout(true); } final boolean fair = ThreadLocalRandom.current().nextBoolean();
public void testTryAcquire_timeout(boolean fair) { final Semaphore s = new Semaphore(0, fair);
Semaphore s = new Semaphore(0, fair); final long startTime = System.nanoTime();
long startTime = System.nanoTime();
try { assertFalse(s.tryAcquire(timeoutMillis(), MILLISECONDS)); } try { assertFalse(s.tryAcquire(timeoutMillis(), MILLISECONDS)); }
catch (InterruptedException e) { threadUnexpectedException(e); } catch (InterruptedException e) { threadUnexpectedException(e); }
assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
@ -230,11 +233,10 @@ public class SemaphoreTest extends JSR166TestCase {
/** /**
* timed tryAcquire(N) times out * timed tryAcquire(N) times out
*/ */
public void testTryAcquireN_timeout() { testTryAcquireN_timeout(false); } public void testTryAcquireN_timeout() {
public void testTryAcquireN_timeout_fair() { testTryAcquireN_timeout(true); } final boolean fair = ThreadLocalRandom.current().nextBoolean();
public void testTryAcquireN_timeout(boolean fair) { final Semaphore s = new Semaphore(2, fair);
Semaphore s = new Semaphore(2, fair); final long startTime = System.nanoTime();
long startTime = System.nanoTime();
try { assertFalse(s.tryAcquire(3, timeoutMillis(), MILLISECONDS)); } try { assertFalse(s.tryAcquire(3, timeoutMillis(), MILLISECONDS)); }
catch (InterruptedException e) { threadUnexpectedException(e); } catch (InterruptedException e) { threadUnexpectedException(e); }
assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
@ -254,7 +256,8 @@ public class SemaphoreTest extends JSR166TestCase {
public void testInterruptible_tryAcquireTimedN_fair() { testInterruptible(true, AcquireMethod.tryAcquireTimedN); } public void testInterruptible_tryAcquireTimedN_fair() { testInterruptible(true, AcquireMethod.tryAcquireTimedN); }
public void testInterruptible(boolean fair, final AcquireMethod acquirer) { public void testInterruptible(boolean fair, final AcquireMethod acquirer) {
final PublicSemaphore s = new PublicSemaphore(0, fair); final PublicSemaphore s = new PublicSemaphore(0, fair);
final Semaphore pleaseInterrupt = new Semaphore(0, fair); final java.util.concurrent.CyclicBarrier pleaseInterrupt
= new java.util.concurrent.CyclicBarrier(2);
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() { public void realRun() {
// Interrupt before acquire // Interrupt before acquire
@ -263,12 +266,7 @@ public class SemaphoreTest extends JSR166TestCase {
acquirer.acquire(s); acquirer.acquire(s);
shouldThrow(); shouldThrow();
} catch (InterruptedException success) {} } catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
// Interrupt during acquire
try {
acquirer.acquire(s);
shouldThrow();
} catch (InterruptedException success) {}
// Interrupt before acquire(N) // Interrupt before acquire(N)
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
@ -276,21 +274,31 @@ public class SemaphoreTest extends JSR166TestCase {
acquirer.acquire(s, 3); acquirer.acquire(s, 3);
shouldThrow(); shouldThrow();
} catch (InterruptedException success) {} } catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
pleaseInterrupt.release(); // Interrupt during acquire
await(pleaseInterrupt);
try {
acquirer.acquire(s);
shouldThrow();
} catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
// Interrupt during acquire(N) // Interrupt during acquire(N)
await(pleaseInterrupt);
try { try {
acquirer.acquire(s, 3); acquirer.acquire(s, 3);
shouldThrow(); shouldThrow();
} catch (InterruptedException success) {} } catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
}}); }});
waitForQueuedThread(s, t); for (int n = 2; n-->0; ) {
t.interrupt();
await(pleaseInterrupt); await(pleaseInterrupt);
waitForQueuedThread(s, t); assertThreadBlocks(t, acquirer.parkedState());
t.interrupt(); t.interrupt();
}
awaitTermination(t); awaitTermination(t);
} }
@ -328,8 +336,8 @@ public class SemaphoreTest extends JSR166TestCase {
waitForQueuedThread(s, t2); waitForQueuedThread(s, t2);
t2.interrupt(); t2.interrupt();
assertThreadStaysAlive(t1); assertThreadBlocks(t1, Thread.State.WAITING);
assertTrue(t2.isAlive()); assertThreadBlocks(t2, Thread.State.WAITING);
s.release(2); s.release(2);
@ -627,8 +635,10 @@ public class SemaphoreTest extends JSR166TestCase {
Thread t2 = newStartedThread(new CheckedRunnable() { Thread t2 = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException { public void realRun() throws InterruptedException {
// Will fail, even though 1 permit is available // Will fail, even though 1 permit is available
assertFalse(s.tryAcquire(0L, MILLISECONDS)); assertFalse(
assertFalse(s.tryAcquire(1, 0L, MILLISECONDS)); s.tryAcquire(randomExpiredTimeout(), randomTimeUnit()));
assertFalse(
s.tryAcquire(1, randomExpiredTimeout(), randomTimeUnit()));
// untimed tryAcquire will barge and succeed // untimed tryAcquire will barge and succeed
assertTrue(s.tryAcquire()); assertTrue(s.tryAcquire());

View File

@ -34,7 +34,6 @@
import static java.util.concurrent.TimeUnit.DAYS; import static java.util.concurrent.TimeUnit.DAYS;
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -275,9 +274,11 @@ public class StampedLockTest extends JSR166TestCase {
long s = assertNonZero(lock.writeLock()); long s = assertNonZero(lock.writeLock());
assertTrue(lock.validate(s)); assertTrue(lock.validate(s));
assertFalse(lock.validate(lock.tryWriteLock())); assertFalse(lock.validate(lock.tryWriteLock()));
assertFalse(lock.validate(lock.tryWriteLock(0L, SECONDS))); assertFalse(lock.validate(lock.tryWriteLock(randomExpiredTimeout(),
randomTimeUnit())));
assertFalse(lock.validate(lock.tryReadLock())); assertFalse(lock.validate(lock.tryReadLock()));
assertFalse(lock.validate(lock.tryReadLock(0L, SECONDS))); assertFalse(lock.validate(lock.tryWriteLock(randomExpiredTimeout(),
randomTimeUnit())));
assertFalse(lock.validate(lock.tryOptimisticRead())); assertFalse(lock.validate(lock.tryOptimisticRead()));
lock.unlockWrite(s); lock.unlockWrite(s);
} }
@ -519,7 +520,7 @@ public class StampedLockTest extends JSR166TestCase {
}}); }});
await(aboutToLock); await(aboutToLock);
waitForThreadToEnterWaitState(t); assertThreadBlocks(t, Thread.State.WAITING);
assertFalse(lock.isWriteLocked()); assertFalse(lock.isWriteLocked());
assertTrue(lock.isReadLocked()); assertTrue(lock.isReadLocked());
lock.unlockRead(rs); lock.unlockRead(rs);
@ -573,8 +574,8 @@ public class StampedLockTest extends JSR166TestCase {
Thread t2 = newStartedThread(acquireReleaseReadLock); Thread t2 = newStartedThread(acquireReleaseReadLock);
await(threadsStarted); await(threadsStarted);
waitForThreadToEnterWaitState(t1); assertThreadBlocks(t1, Thread.State.WAITING);
waitForThreadToEnterWaitState(t2); assertThreadBlocks(t2, Thread.State.WAITING);
assertTrue(lock.isWriteLocked()); assertTrue(lock.isWriteLocked());
assertFalse(lock.isReadLocked()); assertFalse(lock.isReadLocked());
releaseWriteLock(lock, s); releaseWriteLock(lock, s);
@ -780,7 +781,7 @@ public class StampedLockTest extends JSR166TestCase {
await(locked); await(locked);
assertFalse(lock.validate(p)); assertFalse(lock.validate(p));
assertEquals(0L, lock.tryOptimisticRead()); assertEquals(0L, lock.tryOptimisticRead());
waitForThreadToEnterWaitState(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
assertTrue(lock.isWriteLocked()); assertTrue(lock.isWriteLocked());

View File

@ -196,7 +196,8 @@ public class SubmissionPublisherTest extends JSR166TestCase {
} }
/** /**
* A null Executor argument to SubmissionPublisher constructor throws NPE * A null Executor argument to SubmissionPublisher constructor
* throws NullPointerException
*/ */
public void testConstructor3() { public void testConstructor3() {
try { try {
@ -207,7 +208,7 @@ public class SubmissionPublisherTest extends JSR166TestCase {
/** /**
* A negative capacity argument to SubmissionPublisher constructor * A negative capacity argument to SubmissionPublisher constructor
* throws IAE * throws IllegalArgumentException
*/ */
public void testConstructor4() { public void testConstructor4() {
Executor e = Executors.newFixedThreadPool(1); Executor e = Executors.newFixedThreadPool(1);
@ -219,8 +220,9 @@ public class SubmissionPublisherTest extends JSR166TestCase {
/** /**
* A closed publisher reports isClosed with no closedException and * A closed publisher reports isClosed with no closedException and
* throws ISE upon attempted submission; a subsequent close or * throws IllegalStateException upon attempted submission; a
* closeExceptionally has no additional effect. * subsequent close or closeExceptionally has no additional
* effect.
*/ */
public void testClose() { public void testClose() {
SubmissionPublisher<Integer> p = basicPublisher(); SubmissionPublisher<Integer> p = basicPublisher();
@ -240,9 +242,9 @@ public class SubmissionPublisherTest extends JSR166TestCase {
/** /**
* A publisher closedExceptionally reports isClosed with the * A publisher closedExceptionally reports isClosed with the
* closedException and throws ISE upon attempted submission; a * closedException and throws IllegalStateException upon attempted
* subsequent close or closeExceptionally has no additional * submission; a subsequent close or closeExceptionally has no
* effect. * additional effect.
*/ */
public void testCloseExceptionally() { public void testCloseExceptionally() {
SubmissionPublisher<Integer> p = basicPublisher(); SubmissionPublisher<Integer> p = basicPublisher();

View File

@ -45,6 +45,7 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue; import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadLocalRandom;
import junit.framework.Test; import junit.framework.Test;
@ -123,7 +124,7 @@ public class SynchronousQueueTest extends JSR166TestCase {
} }
/** /**
* addAll throws ISE if no active taker * addAll throws IllegalStateException if no active taker
*/ */
public void testAddAll_ISE() { testAddAll_ISE(false); } public void testAddAll_ISE() { testAddAll_ISE(false); }
public void testAddAll_ISE_fair() { testAddAll_ISE(true); } public void testAddAll_ISE_fair() { testAddAll_ISE(true); }
@ -165,7 +166,7 @@ public class SynchronousQueueTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
assertEquals(0, q.remainingCapacity()); assertEquals(0, q.remainingCapacity());
@ -185,6 +186,13 @@ public class SynchronousQueueTest extends JSR166TestCase {
pleaseTake.countDown(); pleaseTake.countDown();
q.put(one); q.put(one);
Thread.currentThread().interrupt();
try {
q.put(99);
shouldThrow();
} catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
pleaseInterrupt.countDown(); pleaseInterrupt.countDown();
try { try {
q.put(99); q.put(99);
@ -199,7 +207,7 @@ public class SynchronousQueueTest extends JSR166TestCase {
catch (InterruptedException e) { threadUnexpectedException(e); } catch (InterruptedException e) { threadUnexpectedException(e); }
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
assertEquals(0, q.remainingCapacity()); assertEquals(0, q.remainingCapacity());
@ -208,9 +216,8 @@ public class SynchronousQueueTest extends JSR166TestCase {
/** /**
* timed offer times out if elements not taken * timed offer times out if elements not taken
*/ */
public void testTimedOffer() { testTimedOffer(false); } public void testTimedOffer() {
public void testTimedOffer_fair() { testTimedOffer(true); } final boolean fair = ThreadLocalRandom.current().nextBoolean();
public void testTimedOffer(boolean fair) {
final SynchronousQueue q = new SynchronousQueue(fair); final SynchronousQueue q = new SynchronousQueue(fair);
final CountDownLatch pleaseInterrupt = new CountDownLatch(1); final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
Thread t = newStartedThread(new CheckedRunnable() { Thread t = newStartedThread(new CheckedRunnable() {
@ -218,15 +225,24 @@ public class SynchronousQueueTest extends JSR166TestCase {
long startTime = System.nanoTime(); long startTime = System.nanoTime();
assertFalse(q.offer(new Object(), timeoutMillis(), MILLISECONDS)); assertFalse(q.offer(new Object(), timeoutMillis(), MILLISECONDS));
assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
Thread.currentThread().interrupt();
try {
q.offer(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS);
shouldThrow();
} catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
pleaseInterrupt.countDown(); pleaseInterrupt.countDown();
try { try {
q.offer(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS); q.offer(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS);
shouldThrow(); shouldThrow();
} catch (InterruptedException success) {} } catch (InterruptedException success) {}
assertFalse(Thread.interrupted());
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -255,11 +271,10 @@ public class SynchronousQueueTest extends JSR166TestCase {
/** /**
* timed poll with nonzero timeout times out if no active putter * timed poll with nonzero timeout times out if no active putter
*/ */
public void testTimedPoll() { testTimedPoll(false); } public void testTimedPoll() {
public void testTimedPoll_fair() { testTimedPoll(true); } final boolean fair = ThreadLocalRandom.current().nextBoolean();
public void testTimedPoll(boolean fair) {
final SynchronousQueue q = new SynchronousQueue(fair); final SynchronousQueue q = new SynchronousQueue(fair);
long startTime = System.nanoTime(); final long startTime = System.nanoTime();
try { assertNull(q.poll(timeoutMillis(), MILLISECONDS)); } try { assertNull(q.poll(timeoutMillis(), MILLISECONDS)); }
catch (InterruptedException e) { threadUnexpectedException(e); } catch (InterruptedException e) { threadUnexpectedException(e); }
assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
@ -269,9 +284,8 @@ public class SynchronousQueueTest extends JSR166TestCase {
* timed poll before a delayed offer times out, returning null; * timed poll before a delayed offer times out, returning null;
* after offer succeeds; on interruption throws * after offer succeeds; on interruption throws
*/ */
public void testTimedPollWithOffer() { testTimedPollWithOffer(false); } public void testTimedPollWithOffer() {
public void testTimedPollWithOffer_fair() { testTimedPollWithOffer(true); } final boolean fair = ThreadLocalRandom.current().nextBoolean();
public void testTimedPollWithOffer(boolean fair) {
final SynchronousQueue q = new SynchronousQueue(fair); final SynchronousQueue q = new SynchronousQueue(fair);
final CountDownLatch pleaseOffer = new CountDownLatch(1); final CountDownLatch pleaseOffer = new CountDownLatch(1);
final CountDownLatch pleaseInterrupt = new CountDownLatch(1); final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
@ -309,7 +323,7 @@ public class SynchronousQueueTest extends JSR166TestCase {
assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -465,7 +479,7 @@ public class SynchronousQueueTest extends JSR166TestCase {
} }
/** /**
* iterator remove throws ISE * iterator remove throws IllegalStateException
*/ */
public void testIteratorRemove() { testIteratorRemove(false); } public void testIteratorRemove() { testIteratorRemove(false); }
public void testIteratorRemove_fair() { testIteratorRemove(true); } public void testIteratorRemove_fair() { testIteratorRemove(true); }

View File

@ -54,43 +54,22 @@ public class SystemTest extends JSR166TestCase {
/** /**
* Nanos between readings of millis is no longer than millis (plus * Nanos between readings of millis is no longer than millis (plus
* possible rounding). * possible rounding), and vice versa.
* This shows only that nano timing not (much) worse than milli. * This shows only that nano timing not (much) worse than milli.
*/ */
public void testNanoTime1() throws InterruptedException { public void testNanoTime() throws InterruptedException {
long m1 = System.currentTimeMillis(); long m0 = System.currentTimeMillis();
Thread.sleep(1); long n0 = System.nanoTime();
long n1 = System.nanoTime();
Thread.sleep(SHORT_DELAY_MS);
long n2 = System.nanoTime();
Thread.sleep(1);
long m2 = System.currentTimeMillis();
long millis = m2 - m1;
long nanos = n2 - n1;
assertTrue(nanos >= 0);
long nanosAsMillis = nanos / 1000000;
assertTrue(nanosAsMillis <= millis + MILLIS_ROUND);
}
/**
* Millis between readings of nanos is less than nanos, adjusting
* for rounding.
* This shows only that nano timing not (much) worse than milli.
*/
public void testNanoTime2() throws InterruptedException {
long n1 = System.nanoTime();
Thread.sleep(1); Thread.sleep(1);
long m1 = System.currentTimeMillis(); long m1 = System.currentTimeMillis();
Thread.sleep(SHORT_DELAY_MS); long n1 = System.nanoTime();
Thread.sleep(50); // avoid possibly scaled SHORT_DELAY_MS
long m2 = System.currentTimeMillis(); long m2 = System.currentTimeMillis();
Thread.sleep(1);
long n2 = System.nanoTime(); long n2 = System.nanoTime();
long millis = m2 - m1; Thread.sleep(1);
long nanos = n2 - n1; long m3 = System.currentTimeMillis();
long n3 = System.nanoTime();
assertTrue(nanos >= 0); assertTrue((n2 - n1) / 1_000_000 <= m3 - m0 + MILLIS_ROUND);
long nanosAsMillis = nanos / 1000000; assertTrue(m2 - m1 <= (n3 - n0) / 1_000_000 + MILLIS_ROUND);
assertTrue(millis <= nanosAsMillis + MILLIS_ROUND);
} }
} }

View File

@ -37,6 +37,8 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
@ -48,11 +50,11 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.FutureTask; import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.RunnableFuture; import java.util.concurrent.RunnableFuture;
import java.util.concurrent.SynchronousQueue; import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -1156,88 +1158,71 @@ public class ThreadPoolExecutorSubclassTest extends JSR166TestCase {
} }
/** /**
* execute throws RejectedExecutionException if saturated. * Submitted tasks are rejected when saturated or shutdown
*/ */
public void testSaturatedExecute() { public void testSubmittedTasksRejectedWhenSaturatedOrShutdown() throws InterruptedException {
final CountDownLatch done = new CountDownLatch(1);
final ThreadPoolExecutor p = final ThreadPoolExecutor p =
new CustomTPE(1, 1, new CustomTPE(1, 1,
LONG_DELAY_MS, MILLISECONDS, LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(1)); new ArrayBlockingQueue<Runnable>(1));
try (PoolCleaner cleaner = cleaner(p, done)) { final int saturatedSize = saturatedSize(p);
Runnable task = new CheckedRunnable() { final ThreadLocalRandom rnd = ThreadLocalRandom.current();
public void realRun() throws InterruptedException { final CountDownLatch threadsStarted = new CountDownLatch(p.getMaximumPoolSize());
await(done); final CountDownLatch done = new CountDownLatch(1);
}}; final Runnable r = () -> {
for (int i = 0; i < 2; ++i) threadsStarted.countDown();
p.execute(task); for (;;) {
for (int i = 0; i < 2; ++i) {
try { try {
p.execute(task); done.await();
shouldThrow(); return;
} catch (RejectedExecutionException success) {} } catch (InterruptedException shutdownNowDeliberatelyIgnored) {}
assertTrue(p.getTaskCount() <= 2);
}
}
}
/**
* executor using CallerRunsPolicy runs task if saturated.
*/
public void testSaturatedExecute2() {
final CountDownLatch done = new CountDownLatch(1);
final ThreadPoolExecutor p =
new CustomTPE(1, 1,
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(1),
new CustomTPE.CallerRunsPolicy());
try (PoolCleaner cleaner = cleaner(p, done)) {
Runnable blocker = new CheckedRunnable() {
public void realRun() throws InterruptedException {
await(done);
}}; }};
p.execute(blocker); final Callable<Boolean> c = () -> {
TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5]; threadsStarted.countDown();
for (int i = 0; i < tasks.length; i++) for (;;) {
tasks[i] = new TrackedNoOpRunnable(); try {
for (int i = 0; i < tasks.length; i++) done.await();
p.execute(tasks[i]); return Boolean.TRUE;
for (int i = 1; i < tasks.length; i++) } catch (InterruptedException shutdownNowDeliberatelyIgnored) {}
assertTrue(tasks[i].done); }};
assertFalse(tasks[0].done); // waiting in queue final boolean shutdownNow = rnd.nextBoolean();
}
}
/**
* executor using DiscardPolicy drops task if saturated.
*/
public void testSaturatedExecute3() {
final TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5];
for (int i = 0; i < tasks.length; ++i)
tasks[i] = new TrackedNoOpRunnable();
final CountDownLatch done = new CountDownLatch(1);
final ThreadPoolExecutor p =
new CustomTPE(1, 1,
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(1),
new CustomTPE.DiscardPolicy());
try (PoolCleaner cleaner = cleaner(p, done)) { try (PoolCleaner cleaner = cleaner(p, done)) {
p.execute(awaiter(done)); // saturate
for (int i = saturatedSize; i--> 0; ) {
for (TrackedNoOpRunnable task : tasks) switch (rnd.nextInt(4)) {
p.execute(task); case 0: p.execute(r); break;
for (int i = 1; i < tasks.length; i++) case 1: assertFalse(p.submit(r).isDone()); break;
assertFalse(tasks[i].done); case 2: assertFalse(p.submit(r, Boolean.TRUE).isDone()); break;
case 3: assertFalse(p.submit(c).isDone()); break;
} }
for (int i = 1; i < tasks.length; i++) }
assertFalse(tasks[i].done);
assertTrue(tasks[0].done); // was waiting in queue await(threadsStarted);
assertTaskSubmissionsAreRejected(p);
if (shutdownNow)
p.shutdownNow();
else
p.shutdown();
// Pool is shutdown, but not yet terminated
assertTaskSubmissionsAreRejected(p);
assertFalse(p.isTerminated());
done.countDown(); // release blocking tasks
assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
assertTaskSubmissionsAreRejected(p);
}
assertEquals(saturatedSize(p)
- (shutdownNow ? p.getQueue().remainingCapacity() : 0),
p.getCompletedTaskCount());
} }
/** /**
* executor using DiscardOldestPolicy drops oldest task if saturated. * executor using DiscardOldestPolicy drops oldest task if saturated.
*/ */
public void testSaturatedExecute4() { public void testSaturatedExecute_DiscardOldestPolicy() {
final CountDownLatch done = new CountDownLatch(1); final CountDownLatch done = new CountDownLatch(1);
LatchAwaiter r1 = awaiter(done); LatchAwaiter r1 = awaiter(done);
LatchAwaiter r2 = awaiter(done); LatchAwaiter r2 = awaiter(done);
@ -1246,7 +1231,7 @@ public class ThreadPoolExecutorSubclassTest extends JSR166TestCase {
new CustomTPE(1, 1, new CustomTPE(1, 1,
LONG_DELAY_MS, MILLISECONDS, LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(1), new ArrayBlockingQueue<Runnable>(1),
new CustomTPE.DiscardOldestPolicy()); new ThreadPoolExecutor.DiscardOldestPolicy());
try (PoolCleaner cleaner = cleaner(p, done)) { try (PoolCleaner cleaner = cleaner(p, done)) {
assertEquals(LatchAwaiter.NEW, r1.state); assertEquals(LatchAwaiter.NEW, r1.state);
assertEquals(LatchAwaiter.NEW, r2.state); assertEquals(LatchAwaiter.NEW, r2.state);
@ -1263,57 +1248,6 @@ public class ThreadPoolExecutorSubclassTest extends JSR166TestCase {
assertEquals(LatchAwaiter.DONE, r3.state); assertEquals(LatchAwaiter.DONE, r3.state);
} }
/**
* execute throws RejectedExecutionException if shutdown
*/
public void testRejectedExecutionExceptionOnShutdown() {
final ThreadPoolExecutor p =
new CustomTPE(1, 1,
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(1));
try { p.shutdown(); } catch (SecurityException ok) { return; }
try (PoolCleaner cleaner = cleaner(p)) {
try {
p.execute(new NoOpRunnable());
shouldThrow();
} catch (RejectedExecutionException success) {}
}
}
/**
* execute using CallerRunsPolicy drops task on shutdown
*/
public void testCallerRunsOnShutdown() {
final ThreadPoolExecutor p =
new CustomTPE(1, 1,
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(1),
new CustomTPE.CallerRunsPolicy());
try { p.shutdown(); } catch (SecurityException ok) { return; }
try (PoolCleaner cleaner = cleaner(p)) {
TrackedNoOpRunnable r = new TrackedNoOpRunnable();
p.execute(r);
assertFalse(r.done);
}
}
/**
* execute using DiscardPolicy drops task on shutdown
*/
public void testDiscardOnShutdown() {
final ThreadPoolExecutor p =
new CustomTPE(1, 1,
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(1),
new CustomTPE.DiscardPolicy());
try { p.shutdown(); } catch (SecurityException ok) { return; }
try (PoolCleaner cleaner = cleaner(p)) {
TrackedNoOpRunnable r = new TrackedNoOpRunnable();
p.execute(r);
assertFalse(r.done);
}
}
/** /**
* execute using DiscardOldestPolicy drops task on shutdown * execute using DiscardOldestPolicy drops task on shutdown
*/ */
@ -1322,7 +1256,7 @@ public class ThreadPoolExecutorSubclassTest extends JSR166TestCase {
new CustomTPE(1, 1, new CustomTPE(1, 1,
LONG_DELAY_MS, MILLISECONDS, LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(1), new ArrayBlockingQueue<Runnable>(1),
new CustomTPE.DiscardOldestPolicy()); new ThreadPoolExecutor.DiscardOldestPolicy());
try { p.shutdown(); } catch (SecurityException ok) { return; } try { p.shutdown(); } catch (SecurityException ok) { return; }
try (PoolCleaner cleaner = cleaner(p)) { try (PoolCleaner cleaner = cleaner(p)) {
@ -1333,18 +1267,15 @@ public class ThreadPoolExecutorSubclassTest extends JSR166TestCase {
} }
/** /**
* execute(null) throws NPE * Submitting null tasks throws NullPointerException
*/ */
public void testExecuteNull() { public void testNullTaskSubmission() {
final ThreadPoolExecutor p = final ThreadPoolExecutor p =
new CustomTPE(1, 2, new CustomTPE(1, 2,
1L, SECONDS, 1L, SECONDS,
new ArrayBlockingQueue<Runnable>(10)); new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(p)) { try (PoolCleaner cleaner = cleaner(p)) {
try { assertNullTaskSubmissionThrowsNullPointerException(p);
p.execute(null);
shouldThrow();
} catch (NullPointerException success) {}
} }
} }
@ -1491,7 +1422,7 @@ public class ThreadPoolExecutorSubclassTest extends JSR166TestCase {
} }
/** /**
* invokeAny(null) throws NPE * invokeAny(null) throws NullPointerException
*/ */
public void testInvokeAny1() throws Exception { public void testInvokeAny1() throws Exception {
final ExecutorService e = final ExecutorService e =
@ -1507,7 +1438,7 @@ public class ThreadPoolExecutorSubclassTest extends JSR166TestCase {
} }
/** /**
* invokeAny(empty collection) throws IAE * invokeAny(empty collection) throws IllegalArgumentException
*/ */
public void testInvokeAny2() throws Exception { public void testInvokeAny2() throws Exception {
final ExecutorService e = final ExecutorService e =
@ -1597,15 +1528,17 @@ public class ThreadPoolExecutorSubclassTest extends JSR166TestCase {
} }
/** /**
* invokeAll(empty collection) returns empty collection * invokeAll(empty collection) returns empty list
*/ */
public void testInvokeAll2() throws Exception { public void testInvokeAll2() throws Exception {
final ExecutorService e = final ExecutorService e =
new CustomTPE(2, 2, new CustomTPE(2, 2,
LONG_DELAY_MS, MILLISECONDS, LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10)); new ArrayBlockingQueue<Runnable>(10));
final Collection<Callable<String>> emptyCollection
= Collections.emptyList();
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>()); List<Future<String>> r = e.invokeAll(emptyCollection);
assertTrue(r.isEmpty()); assertTrue(r.isEmpty());
} }
} }
@ -1680,7 +1613,7 @@ public class ThreadPoolExecutorSubclassTest extends JSR166TestCase {
new ArrayBlockingQueue<Runnable>(10)); new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
try { try {
e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAny(null, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
@ -1698,24 +1631,25 @@ public class ThreadPoolExecutorSubclassTest extends JSR166TestCase {
List<Callable<String>> l = new ArrayList<>(); List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask()); l.add(new StringTask());
try { try {
e.invokeAny(l, MEDIUM_DELAY_MS, null); e.invokeAny(l, randomTimeout(), null);
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
} }
/** /**
* timed invokeAny(empty collection) throws IAE * timed invokeAny(empty collection) throws IllegalArgumentException
*/ */
public void testTimedInvokeAny2() throws Exception { public void testTimedInvokeAny2() throws Exception {
final ExecutorService e = final ExecutorService e =
new CustomTPE(2, 2, new CustomTPE(2, 2,
LONG_DELAY_MS, MILLISECONDS, LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10)); new ArrayBlockingQueue<Runnable>(10));
final Collection<Callable<String>> emptyCollection
= Collections.emptyList();
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
try { try {
e.invokeAny(new ArrayList<Callable<String>>(), e.invokeAny(emptyCollection, randomTimeout(), randomTimeUnit());
MEDIUM_DELAY_MS, MILLISECONDS);
shouldThrow(); shouldThrow();
} catch (IllegalArgumentException success) {} } catch (IllegalArgumentException success) {}
} }
@ -1735,7 +1669,7 @@ public class ThreadPoolExecutorSubclassTest extends JSR166TestCase {
l.add(latchAwaitingStringTask(latch)); l.add(latchAwaitingStringTask(latch));
l.add(null); l.add(null);
try { try {
e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAny(l, randomTimeout(), MILLISECONDS);
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
latch.countDown(); latch.countDown();
@ -1793,7 +1727,7 @@ public class ThreadPoolExecutorSubclassTest extends JSR166TestCase {
new ArrayBlockingQueue<Runnable>(10)); new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
try { try {
e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAll(null, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
@ -1811,23 +1745,25 @@ public class ThreadPoolExecutorSubclassTest extends JSR166TestCase {
List<Callable<String>> l = new ArrayList<>(); List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask()); l.add(new StringTask());
try { try {
e.invokeAll(l, MEDIUM_DELAY_MS, null); e.invokeAll(l, randomTimeout(), null);
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
} }
/** /**
* timed invokeAll(empty collection) returns empty collection * timed invokeAll(empty collection) returns empty list
*/ */
public void testTimedInvokeAll2() throws Exception { public void testTimedInvokeAll2() throws Exception {
final ExecutorService e = final ExecutorService e =
new CustomTPE(2, 2, new CustomTPE(2, 2,
LONG_DELAY_MS, MILLISECONDS, LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10)); new ArrayBlockingQueue<Runnable>(10));
final Collection<Callable<String>> emptyCollection
= Collections.emptyList();
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), List<Future<String>> r =
MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAll(emptyCollection, randomTimeout(), randomTimeUnit());
assertTrue(r.isEmpty()); assertTrue(r.isEmpty());
} }
} }
@ -1845,7 +1781,7 @@ public class ThreadPoolExecutorSubclassTest extends JSR166TestCase {
l.add(new StringTask()); l.add(new StringTask());
l.add(null); l.add(null);
try { try {
e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAll(l, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }

View File

@ -38,6 +38,8 @@ import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
@ -53,8 +55,14 @@ import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.SynchronousQueue; import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor.AbortPolicy;
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
import java.util.concurrent.ThreadPoolExecutor.DiscardPolicy;
import java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import junit.framework.Test; import junit.framework.Test;
import junit.framework.TestSuite; import junit.framework.TestSuite;
@ -309,8 +317,7 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
LONG_DELAY_MS, MILLISECONDS, LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10)); new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(p)) { try (PoolCleaner cleaner = cleaner(p)) {
assertTrue(p.getRejectedExecutionHandler() assertTrue(p.getRejectedExecutionHandler() instanceof AbortPolicy);
instanceof ThreadPoolExecutor.AbortPolicy);
} }
} }
@ -497,8 +504,8 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
assertFalse(p.awaitTermination(Long.MIN_VALUE, MILLISECONDS)); assertFalse(p.awaitTermination(Long.MIN_VALUE, MILLISECONDS));
assertFalse(p.awaitTermination(-1L, NANOSECONDS)); assertFalse(p.awaitTermination(-1L, NANOSECONDS));
assertFalse(p.awaitTermination(-1L, MILLISECONDS)); assertFalse(p.awaitTermination(-1L, MILLISECONDS));
assertFalse(p.awaitTermination(0L, NANOSECONDS)); assertFalse(p.awaitTermination(randomExpiredTimeout(),
assertFalse(p.awaitTermination(0L, MILLISECONDS)); randomTimeUnit()));
long timeoutNanos = 999999L; long timeoutNanos = 999999L;
long startTime = System.nanoTime(); long startTime = System.nanoTime();
assertFalse(p.awaitTermination(timeoutNanos, NANOSECONDS)); assertFalse(p.awaitTermination(timeoutNanos, NANOSECONDS));
@ -1079,149 +1086,76 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
p.submit(task).get(); p.submit(task).get();
}}); }});
await(threadStarted); await(threadStarted); // ensure quiescence
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
} }
/** /**
* execute throws RejectedExecutionException if saturated. * Submitted tasks are rejected when saturated or shutdown
*/ */
public void testSaturatedExecute() { public void testSubmittedTasksRejectedWhenSaturatedOrShutdown() throws InterruptedException {
final ThreadPoolExecutor p = new ThreadPoolExecutor(
1, 1, 1, SECONDS, new ArrayBlockingQueue<Runnable>(1));
final int saturatedSize = saturatedSize(p);
final ThreadLocalRandom rnd = ThreadLocalRandom.current();
final CountDownLatch threadsStarted = new CountDownLatch(p.getMaximumPoolSize());
final CountDownLatch done = new CountDownLatch(1); final CountDownLatch done = new CountDownLatch(1);
final ThreadPoolExecutor p = final Runnable r = () -> {
new ThreadPoolExecutor(1, 1, threadsStarted.countDown();
LONG_DELAY_MS, MILLISECONDS, for (;;) {
new ArrayBlockingQueue<Runnable>(1));
try (PoolCleaner cleaner = cleaner(p, done)) {
Runnable task = new CheckedRunnable() {
public void realRun() throws InterruptedException {
await(done);
}};
for (int i = 0; i < 2; ++i)
p.execute(task);
for (int i = 0; i < 2; ++i) {
try { try {
p.execute(task); done.await();
shouldThrow(); return;
} catch (RejectedExecutionException success) {} } catch (InterruptedException shutdownNowDeliberatelyIgnored) {}
assertTrue(p.getTaskCount() <= 2);
}
}
}
/**
* submit(runnable) throws RejectedExecutionException if saturated.
*/
public void testSaturatedSubmitRunnable() {
final CountDownLatch done = new CountDownLatch(1);
final ThreadPoolExecutor p =
new ThreadPoolExecutor(1, 1,
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(1));
try (PoolCleaner cleaner = cleaner(p, done)) {
Runnable task = new CheckedRunnable() {
public void realRun() throws InterruptedException {
await(done);
}}; }};
for (int i = 0; i < 2; ++i) final Callable<Boolean> c = () -> {
p.submit(task); threadsStarted.countDown();
for (int i = 0; i < 2; ++i) { for (;;) {
try { try {
p.execute(task); done.await();
shouldThrow(); return Boolean.TRUE;
} catch (RejectedExecutionException success) {} } catch (InterruptedException shutdownNowDeliberatelyIgnored) {}
assertTrue(p.getTaskCount() <= 2);
}
}
}
/**
* submit(callable) throws RejectedExecutionException if saturated.
*/
public void testSaturatedSubmitCallable() {
final CountDownLatch done = new CountDownLatch(1);
final ThreadPoolExecutor p =
new ThreadPoolExecutor(1, 1,
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(1));
try (PoolCleaner cleaner = cleaner(p, done)) {
Runnable task = new CheckedRunnable() {
public void realRun() throws InterruptedException {
await(done);
}}; }};
for (int i = 0; i < 2; ++i) final boolean shutdownNow = rnd.nextBoolean();
p.execute(task);
for (int i = 0; i < 2; ++i) {
try {
p.execute(task);
shouldThrow();
} catch (RejectedExecutionException success) {}
assertTrue(p.getTaskCount() <= 2);
}
}
}
/**
* executor using CallerRunsPolicy runs task if saturated.
*/
public void testSaturatedExecute2() {
final ThreadPoolExecutor p =
new ThreadPoolExecutor(1, 1,
LONG_DELAY_MS,
MILLISECONDS,
new ArrayBlockingQueue<Runnable>(1),
new ThreadPoolExecutor.CallerRunsPolicy());
try (PoolCleaner cleaner = cleaner(p)) {
final CountDownLatch done = new CountDownLatch(1);
Runnable blocker = new CheckedRunnable() {
public void realRun() throws InterruptedException {
await(done);
}};
p.execute(blocker);
TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5];
for (int i = 0; i < tasks.length; i++)
tasks[i] = new TrackedNoOpRunnable();
for (int i = 0; i < tasks.length; i++)
p.execute(tasks[i]);
for (int i = 1; i < tasks.length; i++)
assertTrue(tasks[i].done);
assertFalse(tasks[0].done); // waiting in queue
done.countDown();
}
}
/**
* executor using DiscardPolicy drops task if saturated.
*/
public void testSaturatedExecute3() {
final CountDownLatch done = new CountDownLatch(1);
final TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5];
for (int i = 0; i < tasks.length; ++i)
tasks[i] = new TrackedNoOpRunnable();
final ThreadPoolExecutor p =
new ThreadPoolExecutor(1, 1,
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(1),
new ThreadPoolExecutor.DiscardPolicy());
try (PoolCleaner cleaner = cleaner(p, done)) { try (PoolCleaner cleaner = cleaner(p, done)) {
p.execute(awaiter(done)); // saturate
for (int i = saturatedSize; i--> 0; ) {
for (TrackedNoOpRunnable task : tasks) switch (rnd.nextInt(4)) {
p.execute(task); case 0: p.execute(r); break;
for (int i = 1; i < tasks.length; i++) case 1: assertFalse(p.submit(r).isDone()); break;
assertFalse(tasks[i].done); case 2: assertFalse(p.submit(r, Boolean.TRUE).isDone()); break;
case 3: assertFalse(p.submit(c).isDone()); break;
} }
for (int i = 1; i < tasks.length; i++) }
assertFalse(tasks[i].done);
assertTrue(tasks[0].done); // was waiting in queue await(threadsStarted);
assertTaskSubmissionsAreRejected(p);
if (shutdownNow)
p.shutdownNow();
else
p.shutdown();
// Pool is shutdown, but not yet terminated
assertTaskSubmissionsAreRejected(p);
assertFalse(p.isTerminated());
done.countDown(); // release blocking tasks
assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
assertTaskSubmissionsAreRejected(p);
}
assertEquals(saturatedSize(p)
- (shutdownNow ? p.getQueue().remainingCapacity() : 0),
p.getCompletedTaskCount());
} }
/** /**
* executor using DiscardOldestPolicy drops oldest task if saturated. * executor using DiscardOldestPolicy drops oldest task if saturated.
*/ */
public void testSaturatedExecute4() { public void testSaturatedExecute_DiscardOldestPolicy() {
final CountDownLatch done = new CountDownLatch(1); final CountDownLatch done = new CountDownLatch(1);
LatchAwaiter r1 = awaiter(done); LatchAwaiter r1 = awaiter(done);
LatchAwaiter r2 = awaiter(done); LatchAwaiter r2 = awaiter(done);
@ -1230,7 +1164,7 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
new ThreadPoolExecutor(1, 1, new ThreadPoolExecutor(1, 1,
LONG_DELAY_MS, MILLISECONDS, LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(1), new ArrayBlockingQueue<Runnable>(1),
new ThreadPoolExecutor.DiscardOldestPolicy()); new DiscardOldestPolicy());
try (PoolCleaner cleaner = cleaner(p, done)) { try (PoolCleaner cleaner = cleaner(p, done)) {
assertEquals(LatchAwaiter.NEW, r1.state); assertEquals(LatchAwaiter.NEW, r1.state);
assertEquals(LatchAwaiter.NEW, r2.state); assertEquals(LatchAwaiter.NEW, r2.state);
@ -1247,59 +1181,6 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
assertEquals(LatchAwaiter.DONE, r3.state); assertEquals(LatchAwaiter.DONE, r3.state);
} }
/**
* execute throws RejectedExecutionException if shutdown
*/
public void testRejectedExecutionExceptionOnShutdown() {
final ThreadPoolExecutor p =
new ThreadPoolExecutor(1, 1,
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(1));
try { p.shutdown(); } catch (SecurityException ok) { return; }
try (PoolCleaner cleaner = cleaner(p)) {
try {
p.execute(new NoOpRunnable());
shouldThrow();
} catch (RejectedExecutionException success) {}
}
}
/**
* execute using CallerRunsPolicy drops task on shutdown
*/
public void testCallerRunsOnShutdown() {
RejectedExecutionHandler h = new ThreadPoolExecutor.CallerRunsPolicy();
final ThreadPoolExecutor p =
new ThreadPoolExecutor(1, 1,
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(1), h);
try { p.shutdown(); } catch (SecurityException ok) { return; }
try (PoolCleaner cleaner = cleaner(p)) {
TrackedNoOpRunnable r = new TrackedNoOpRunnable();
p.execute(r);
assertFalse(r.done);
}
}
/**
* execute using DiscardPolicy drops task on shutdown
*/
public void testDiscardOnShutdown() {
final ThreadPoolExecutor p =
new ThreadPoolExecutor(1, 1,
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(1),
new ThreadPoolExecutor.DiscardPolicy());
try { p.shutdown(); } catch (SecurityException ok) { return; }
try (PoolCleaner cleaner = cleaner(p)) {
TrackedNoOpRunnable r = new TrackedNoOpRunnable();
p.execute(r);
assertFalse(r.done);
}
}
/** /**
* execute using DiscardOldestPolicy drops task on shutdown * execute using DiscardOldestPolicy drops task on shutdown
*/ */
@ -1308,7 +1189,7 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
new ThreadPoolExecutor(1, 1, new ThreadPoolExecutor(1, 1,
LONG_DELAY_MS, MILLISECONDS, LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(1), new ArrayBlockingQueue<Runnable>(1),
new ThreadPoolExecutor.DiscardOldestPolicy()); new DiscardOldestPolicy());
try { p.shutdown(); } catch (SecurityException ok) { return; } try { p.shutdown(); } catch (SecurityException ok) { return; }
try (PoolCleaner cleaner = cleaner(p)) { try (PoolCleaner cleaner = cleaner(p)) {
@ -1319,18 +1200,15 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
} }
/** /**
* execute(null) throws NPE * Submitting null tasks throws NullPointerException
*/ */
public void testExecuteNull() { public void testNullTaskSubmission() {
final ThreadPoolExecutor p = final ThreadPoolExecutor p =
new ThreadPoolExecutor(1, 2, new ThreadPoolExecutor(1, 2,
1L, SECONDS, 1L, SECONDS,
new ArrayBlockingQueue<Runnable>(10)); new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(p)) { try (PoolCleaner cleaner = cleaner(p)) {
try { assertNullTaskSubmissionThrowsNullPointerException(p);
p.execute(null);
shouldThrow();
} catch (NullPointerException success) {}
} }
} }
@ -1522,7 +1400,7 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
} }
/** /**
* invokeAny(empty collection) throws IAE * invokeAny(empty collection) throws IllegalArgumentException
*/ */
public void testInvokeAny2() throws Exception { public void testInvokeAny2() throws Exception {
final ExecutorService e = final ExecutorService e =
@ -1612,15 +1490,17 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
} }
/** /**
* invokeAll(empty collection) returns empty collection * invokeAll(empty collection) returns empty list
*/ */
public void testInvokeAll2() throws InterruptedException { public void testInvokeAll2() throws InterruptedException {
final ExecutorService e = final ExecutorService e =
new ThreadPoolExecutor(2, 2, new ThreadPoolExecutor(2, 2,
LONG_DELAY_MS, MILLISECONDS, LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10)); new ArrayBlockingQueue<Runnable>(10));
final Collection<Callable<String>> emptyCollection
= Collections.emptyList();
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>()); List<Future<String>> r = e.invokeAll(emptyCollection);
assertTrue(r.isEmpty()); assertTrue(r.isEmpty());
} }
} }
@ -1695,7 +1575,7 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
new ArrayBlockingQueue<Runnable>(10)); new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
try { try {
e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAny(null, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
@ -1713,14 +1593,14 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
List<Callable<String>> l = new ArrayList<>(); List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask()); l.add(new StringTask());
try { try {
e.invokeAny(l, MEDIUM_DELAY_MS, null); e.invokeAny(l, randomTimeout(), null);
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
} }
/** /**
* timed invokeAny(empty collection) throws IAE * timed invokeAny(empty collection) throws IllegalArgumentException
*/ */
public void testTimedInvokeAny2() throws Exception { public void testTimedInvokeAny2() throws Exception {
final ExecutorService e = final ExecutorService e =
@ -1730,14 +1610,14 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
try { try {
e.invokeAny(new ArrayList<Callable<String>>(), e.invokeAny(new ArrayList<Callable<String>>(),
MEDIUM_DELAY_MS, MILLISECONDS); randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (IllegalArgumentException success) {} } catch (IllegalArgumentException success) {}
} }
} }
/** /**
* timed invokeAny(c) throws NPE if c has null elements * timed invokeAny(c) throws NullPointerException if c has null elements
*/ */
public void testTimedInvokeAny3() throws Exception { public void testTimedInvokeAny3() throws Exception {
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
@ -1750,7 +1630,7 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
l.add(latchAwaitingStringTask(latch)); l.add(latchAwaitingStringTask(latch));
l.add(null); l.add(null);
try { try {
e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAny(l, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
latch.countDown(); latch.countDown();
@ -1808,7 +1688,7 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
new ArrayBlockingQueue<Runnable>(10)); new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
try { try {
e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAll(null, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
@ -1826,23 +1706,25 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
List<Callable<String>> l = new ArrayList<>(); List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask()); l.add(new StringTask());
try { try {
e.invokeAll(l, MEDIUM_DELAY_MS, null); e.invokeAll(l, randomTimeout(), null);
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
} }
/** /**
* timed invokeAll(empty collection) returns empty collection * timed invokeAll(empty collection) returns empty list
*/ */
public void testTimedInvokeAll2() throws InterruptedException { public void testTimedInvokeAll2() throws InterruptedException {
final ExecutorService e = final ExecutorService e =
new ThreadPoolExecutor(2, 2, new ThreadPoolExecutor(2, 2,
LONG_DELAY_MS, MILLISECONDS, LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10)); new ArrayBlockingQueue<Runnable>(10));
final Collection<Callable<String>> emptyCollection
= Collections.emptyList();
try (PoolCleaner cleaner = cleaner(e)) { try (PoolCleaner cleaner = cleaner(e)) {
List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), List<Future<String>> r =
MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAll(emptyCollection, randomTimeout(), randomTimeUnit());
assertTrue(r.isEmpty()); assertTrue(r.isEmpty());
} }
} }
@ -1860,7 +1742,7 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
l.add(new StringTask()); l.add(new StringTask());
l.add(null); l.add(null);
try { try {
e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); e.invokeAll(l, randomTimeout(), randomTimeUnit());
shouldThrow(); shouldThrow();
} catch (NullPointerException success) {} } catch (NullPointerException success) {}
} }
@ -2102,4 +1984,31 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
} }
} }
/** Directly test simple ThreadPoolExecutor RejectedExecutionHandlers. */
public void testStandardRejectedExecutionHandlers() {
final ThreadPoolExecutor p =
new ThreadPoolExecutor(1, 1, 1, SECONDS,
new ArrayBlockingQueue<Runnable>(1));
final AtomicReference<Thread> thread = new AtomicReference<>();
final Runnable r = new Runnable() { public void run() {
thread.set(Thread.currentThread()); }};
try {
new AbortPolicy().rejectedExecution(r, p);
shouldThrow();
} catch (RejectedExecutionException success) {}
assertNull(thread.get());
new DiscardPolicy().rejectedExecution(r, p);
assertNull(thread.get());
new CallerRunsPolicy().rejectedExecution(r, p);
assertSame(Thread.currentThread(), thread.get());
// check that pool was not perturbed by handlers
assertTrue(p.getRejectedExecutionHandler() instanceof AbortPolicy);
assertEquals(0, p.getTaskCount());
assertTrue(p.getQueue().isEmpty());
}
} }

View File

@ -553,7 +553,7 @@ public class TimeUnitTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }
@ -586,7 +586,7 @@ public class TimeUnitTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
s.interrupt(); s.interrupt();
@ -617,7 +617,7 @@ public class TimeUnitTest extends JSR166TestCase {
}}); }});
await(pleaseInterrupt); await(pleaseInterrupt);
assertThreadStaysAlive(t); assertThreadBlocks(t, Thread.State.TIMED_WAITING);
t.interrupt(); t.interrupt();
awaitTermination(t); awaitTermination(t);
} }

View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8183591
* @summary Test decoding of DER length fields containing Integer.MAX_VALUE
* @run main TestMaxLengthDER
*/
import java.io.*;
import java.math.*;
import java.security.*;
import java.security.spec.*;
public class TestMaxLengthDER {
public static void main(String[] args) throws Exception {
String message = "Message";
Signature sig = Signature.getInstance("SHA256withDSA");
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
SecureRandom rnd = new SecureRandom();
rnd.setSeed(1);
kpg.initialize(2048, rnd);
KeyPair kp = kpg.generateKeyPair();
sig.initSign(kp.getPrivate());
sig.update(message.getBytes());
byte[] sigData = sig.sign();
// Set the length of the second integer to Integer.MAX_VALUE
// First copy all the signature data to the correct location
int lengthPos = sigData[3] + 5;
byte[] modifiedSigData = new byte[sigData.length + 4];
System.arraycopy(sigData, 0, modifiedSigData, 0, lengthPos);
System.arraycopy(sigData, lengthPos + 1, modifiedSigData,
lengthPos + 5, sigData.length - (lengthPos + 1));
// Increase the length (in bytes) of the sequence to account for
// the larger length field
modifiedSigData[1] += 4;
// Modify the length field
modifiedSigData[lengthPos] = (byte) 0x84;
modifiedSigData[lengthPos + 1] = (byte) 0x7F;
modifiedSigData[lengthPos + 2] = (byte) 0xFF;
modifiedSigData[lengthPos + 3] = (byte) 0xFF;
modifiedSigData[lengthPos + 4] = (byte) 0xFF;
sig.initVerify(kp.getPublic());
sig.update(message.getBytes());
try {
sig.verify(modifiedSigData);
throw new RuntimeException("No exception on misencoded signature");
} catch (SignatureException ex) {
if (ex.getCause() instanceof EOFException) {
// this is expected
} else {
throw ex;
}
}
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2009, 2017 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
@ -48,30 +48,37 @@ public class BadValue {
if (bs.length != 6 || in.available() != 0) { if (bs.length != 6 || in.available() != 0) {
throw new Exception("Second read error"); throw new Exception("Second read error");
} }
// MAX read as much as it can // MAX length results in exception
in = new ByteArrayInputStream(new byte[10]); in = new ByteArrayInputStream(new byte[10]);
try {
bs = IOUtils.readFully(in, Integer.MAX_VALUE, true); bs = IOUtils.readFully(in, Integer.MAX_VALUE, true);
if (bs.length != 10 || in.available() != 0) { throw new Exception("No exception on MAX_VALUE length");
throw new Exception("Second read error"); } catch (EOFException ex) {
// this is expected
} catch (IOException ex) {
throw ex;
} }
// MAX ignore readAll // -1 length results in exception
in = new ByteArrayInputStream(new byte[10]); in = new ByteArrayInputStream(new byte[10]);
bs = IOUtils.readFully(in, Integer.MAX_VALUE, false); try {
if (bs.length != 10 || in.available() != 0) { bs = IOUtils.readFully(in, -1, true);
throw new Exception("Second read error"); throw new Exception("No exception on -1 length");
} catch (IOException ex) {
// this is expected
} }
// 20>10, readAll means failure // 20>10, readAll means failure
in = new ByteArrayInputStream(new byte[10]); in = new ByteArrayInputStream(new byte[10]);
try { try {
bs = IOUtils.readFully(in, 20, true); bs = IOUtils.readFully(in, 20, true);
throw new Exception("Third read error"); throw new Exception("No exception on EOF");
} catch (EOFException e) { } catch (EOFException e) {
// OK // OK
} }
int bignum = 10 * 1024 * 1024; int bignum = 10 * 1024 * 1024;
bs = IOUtils.readFully(new SuperSlowStream(bignum), -1, true); bs = IOUtils.readFully(new SuperSlowStream(bignum), bignum, true);
if (bs.length != bignum) { if (bs.length != bignum) {
throw new Exception("Fourth read error"); throw new Exception("Read returned small array");
} }
// Test DerValue // Test DerValue