8286294: ForkJoinPool.commonPool().close() spins
Reviewed-by: alanb
This commit is contained in:
parent
d4474b5816
commit
4f5d73f2d4
@ -3529,6 +3529,54 @@ public class ForkJoinPool extends AbstractExecutorService {
|
|||||||
return (helpQuiescePool(this, unit.toNanos(timeout), false) > 0);
|
return (helpQuiescePool(this, unit.toNanos(timeout), false) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unless this is the {@link #commonPool()}, initiates an orderly
|
||||||
|
* shutdown in which previously submitted tasks are executed, but
|
||||||
|
* no new tasks will be accepted, and waits until all tasks have
|
||||||
|
* completed execution and the executor has terminated.
|
||||||
|
*
|
||||||
|
* <p> If already terminated, or this is the {@link
|
||||||
|
* #commonPool()}, this method has no effect on execution, and
|
||||||
|
* does not wait. Otherwise, if interrupted while waiting, this
|
||||||
|
* method stops all executing tasks as if by invoking {@link
|
||||||
|
* #shutdownNow()}. It then continues to wait until all actively
|
||||||
|
* executing tasks have completed. Tasks that were awaiting
|
||||||
|
* execution are not executed. The interrupt status will be
|
||||||
|
* re-asserted before this method returns.
|
||||||
|
*
|
||||||
|
* @throws SecurityException if a security manager exists and
|
||||||
|
* shutting down this ExecutorService may manipulate
|
||||||
|
* threads that the caller is not permitted to modify
|
||||||
|
* because it does not hold {@link
|
||||||
|
* java.lang.RuntimePermission}{@code ("modifyThread")},
|
||||||
|
* or the security manager's {@code checkAccess} method
|
||||||
|
* denies access.
|
||||||
|
* @since 19
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
if ((config & ISCOMMON) == 0) {
|
||||||
|
boolean terminated = tryTerminate(false, false);
|
||||||
|
if (!terminated) {
|
||||||
|
shutdown();
|
||||||
|
boolean interrupted = false;
|
||||||
|
while (!terminated) {
|
||||||
|
try {
|
||||||
|
terminated = awaitTermination(1L, TimeUnit.DAYS);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
if (!interrupted) {
|
||||||
|
shutdownNow();
|
||||||
|
interrupted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (interrupted) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for extending managed parallelism for tasks running
|
* Interface for extending managed parallelism for tasks running
|
||||||
* in {@link ForkJoinPool}s.
|
* in {@link ForkJoinPool}s.
|
||||||
|
@ -55,7 +55,7 @@ public class ForkJoinPool19Test extends JSR166TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Test suite() {
|
public static Test suite() {
|
||||||
return new TestSuite(ForkJoinPool8Test.class);
|
return new TestSuite(ForkJoinPool19Test.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -264,21 +264,29 @@ public class ForkJoinPool19Test extends JSR166TestCase {
|
|||||||
* lazySubmit submits a task that is not executed until new
|
* lazySubmit submits a task that is not executed until new
|
||||||
* workers are created or it is explicitly joined by a worker.
|
* workers are created or it is explicitly joined by a worker.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("removal")
|
||||||
public void testLazySubmit() {
|
public void testLazySubmit() {
|
||||||
|
ForkJoinPool p;
|
||||||
|
try {
|
||||||
|
p = new ForkJoinPool();
|
||||||
|
} catch (java.security.AccessControlException e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FibAction f = new FibAction(8);
|
||||||
|
RecursiveAction j = new RecursiveAction() {
|
||||||
|
protected void compute() {
|
||||||
|
f.join();
|
||||||
|
}};
|
||||||
RecursiveAction a = new CheckedRecursiveAction() {
|
RecursiveAction a = new CheckedRecursiveAction() {
|
||||||
protected void realCompute() {
|
protected void realCompute() {
|
||||||
final ForkJoinPool p = mainPool();
|
p.invoke(new FibAction(8));
|
||||||
FibAction f = new FibAction(8);
|
|
||||||
p.lazySubmit(f);
|
p.lazySubmit(f);
|
||||||
checkNotDone(f);
|
p.invoke(new FibAction(8));
|
||||||
FibAction g = new FibAction(8);
|
p.invoke(j);
|
||||||
p.submit(g);
|
|
||||||
g.join();
|
|
||||||
f.join();
|
|
||||||
assertEquals(21, f.result);
|
assertEquals(21, f.result);
|
||||||
checkCompletedNormally(f);
|
checkCompletedNormally(f);
|
||||||
}};
|
}};
|
||||||
testInvokeOnPool(mainPool(), a);
|
testInvokeOnPool(p, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -492,4 +500,40 @@ public class ForkJoinPool19Test extends JSR166TestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implicitly closing a new pool using try-with-resources terminates it
|
||||||
|
*/
|
||||||
|
public void testClose() {
|
||||||
|
ForkJoinTask f = new FibAction(8);
|
||||||
|
ForkJoinPool pool = null;
|
||||||
|
try (ForkJoinPool p = new ForkJoinPool()) {
|
||||||
|
pool = p;
|
||||||
|
p.execute(f);
|
||||||
|
}
|
||||||
|
checkCompletedNormally(f);
|
||||||
|
assertTrue(pool != null && pool.isTerminated());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implicitly closing common pool using try-with-resources has no effect.
|
||||||
|
*/
|
||||||
|
public void testCloseCommonPool() {
|
||||||
|
ForkJoinTask f = new FibAction(8);
|
||||||
|
ForkJoinPool pool;
|
||||||
|
try (ForkJoinPool p = pool = ForkJoinPool.commonPool()) {
|
||||||
|
p.execute(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertFalse(pool.isShutdown());
|
||||||
|
assertFalse(pool.isTerminating());
|
||||||
|
assertFalse(pool.isTerminated());
|
||||||
|
|
||||||
|
String prop = System.getProperty(
|
||||||
|
"java.util.concurrent.ForkJoinPool.common.parallelism");
|
||||||
|
if (! "0".equals(prop)) {
|
||||||
|
f.join();
|
||||||
|
checkCompletedNormally(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1721,19 +1721,17 @@ public class ForkJoinTaskTest extends JSR166TestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// adaptInterruptible deferred to its own independent change
|
|
||||||
// https://bugs.openjdk.java.net/browse/JDK-8246587
|
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * adaptInterruptible(callable).toString() contains toString of wrapped task
|
* adaptInterruptible(callable).toString() contains toString of wrapped task
|
||||||
// */
|
*/
|
||||||
// public void testAdaptInterruptible_Callable_toString() {
|
public void testAdaptInterruptible_Callable_toString() {
|
||||||
// if (testImplementationDetails) {
|
if (testImplementationDetails) {
|
||||||
// Callable<String> c = () -> "";
|
Callable<String> c = () -> "";
|
||||||
// ForkJoinTask<String> task = ForkJoinTask.adaptInterruptible(c);
|
ForkJoinTask<String> task = ForkJoinTask.adaptInterruptible(c);
|
||||||
// assertEquals(
|
assertEquals(
|
||||||
// identityString(task) + "[Wrapped task = " + c.toString() + "]",
|
identityString(task) + "[Wrapped task = " + c.toString() + "]",
|
||||||
// task.toString());
|
task.toString());
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user