From ffae33da926c6ec4da9a7760d98323d476114ce7 Mon Sep 17 00:00:00 2001 From: Marco Terzer Date: Wed, 24 Jul 2019 00:46:25 +1000 Subject: [PATCH] ShutdownableThread now waits forever if await time is zero --- .../java/org/tools4j/nobark/run/Joinable.java | 2 +- .../org/tools4j/nobark/run/Shutdownable.java | 12 +++++------ .../nobark/run/ShutdownableThread.java | 21 ++++++++----------- .../org/tools4j/nobark/run/ThreadLike.java | 2 +- .../org/tools4j/nobark/run/ThreadState.java | 2 +- .../org/tools4j/nobark/run/package-info.java | 2 +- .../nobark/run/ShutdownableThreadTest.java | 17 +++++++++------ 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/main/java/org/tools4j/nobark/run/Joinable.java b/src/main/java/org/tools4j/nobark/run/Joinable.java index ada0589..587b4f7 100644 --- a/src/main/java/org/tools4j/nobark/run/Joinable.java +++ b/src/main/java/org/tools4j/nobark/run/Joinable.java @@ -1,7 +1,7 @@ /** * The MIT License (MIT) * - * Copyright (c) 2018 nobark (tools4j), Marco Terzer, Anton Anufriev + * Copyright (c) 2019 nobark (tools4j), Marco Terzer, Anton Anufriev * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/org/tools4j/nobark/run/Shutdownable.java b/src/main/java/org/tools4j/nobark/run/Shutdownable.java index 1dff3e5..131c92c 100644 --- a/src/main/java/org/tools4j/nobark/run/Shutdownable.java +++ b/src/main/java/org/tools4j/nobark/run/Shutdownable.java @@ -69,19 +69,17 @@ public interface Shutdownable { boolean isShutdown(); /** - * Returns {@code true} if this service has terminated following shut down. Note that - * {@code isTerminated} is never {@code true} unless either {@code shutdown} or - * {@code shutdownNow} was called first. + * Returns {@code true} if this service has terminated. * - * @return {@code true} if the service has terminated following shut down + * @return {@code true} if the service has terminated. */ boolean isTerminated(); /** - * Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, - * whichever happens first. + * Blocks until this service has terminated, or the timeout occurs, whichever happens first. + * Zero timeout means waiting forever. * - * @param timeout the maximum time to wait + * @param timeout the maximum time to wait, zero to wait indefinitely * @param unit the time unit of the timeout argument * @return {@code true} if this executor terminated and * {@code false} if the timeout elapsed before termination diff --git a/src/main/java/org/tools4j/nobark/run/ShutdownableThread.java b/src/main/java/org/tools4j/nobark/run/ShutdownableThread.java index 351e8ff..9a2dbf9 100644 --- a/src/main/java/org/tools4j/nobark/run/ShutdownableThread.java +++ b/src/main/java/org/tools4j/nobark/run/ShutdownableThread.java @@ -52,9 +52,9 @@ public class ShutdownableThread implements ThreadLike, Shutdownable { * Constructor for shutdownable thread; it is recommended to use the static start(..) methods instead. * * @param mainRunnableFactory the factory for the main runnable; - * the {@link #isMainRunning} condition is passed to the factory as lambda + * the {@link #keepMainRunning} condition is passed to the factory as lambda * @param shutdownRunnableFactory the factory for the shutdown phase runnable; - * the {@link #isShutdownRunning} condition is passed to the factory as lambda + * the {@link #keepShutdownRunning} condition is passed to the factory as lambda * @param threadFactory the factory to provide the thread */ protected ShutdownableThread(final RunnableFactory mainRunnableFactory, @@ -70,9 +70,9 @@ protected ShutdownableThread(final RunnableFactory mainRunnableFactory, * Creates, starts and returns a new shutdownable thread. * * @param mainRunnableFactory the factory for the main runnable; - * the {@link #isMainRunning} condition is passed to the factory as lambda + * the {@link #keepMainRunning} condition is passed to the factory as lambda * @param shutdownRunnableFactory the factory for the shutdown phase runnable; - * the {@link #isShutdownRunning} condition is passed to the factory as lambda + * the {@link #keepShutdownRunning} condition is passed to the factory as lambda * @param threadFactory the factory to provide the thread * @return the newly created and started shutdownable thread */ @@ -83,8 +83,8 @@ public static ShutdownableThread start(final RunnableFactory mainRunnableFactory } private void run() { - final Runnable main = mainRunnableFactory.create(this::isMainRunning); - final Runnable shutdown = shutdownRunnableFactory.create(this::isShutdownRunning); + final Runnable main = mainRunnableFactory.create(this::keepMainRunning); + final Runnable shutdown = shutdownRunnableFactory.create(this::keepShutdownRunning); main.run(); shutdown.run(); } @@ -104,11 +104,11 @@ public List shutdownNow() { return Collections.emptyList(); } - private boolean isMainRunning() { + private boolean keepMainRunning() { return (state.get() & SHUTDOWN) == 0; } - private boolean isShutdownRunning() { + private boolean keepShutdownRunning() { return (state.get() & SHUTDOWN_NOW) == 0; } @@ -119,7 +119,7 @@ public boolean isShutdown() { @Override public boolean isTerminated() { - return isShutdown() && threadState() == Thread.State.TERMINATED; + return threadState() == Thread.State.TERMINATED; } @Override @@ -130,9 +130,6 @@ public boolean awaitTermination(final long timeout, final TimeUnit unit) { if (isTerminated()) { return true; } - if (timeout == 0) { - return isTerminated(); - } final long millis = unit.toMillis(timeout); final long nanos = unit.toNanos(timeout - unit.convert(millis, TimeUnit.MILLISECONDS)); try { diff --git a/src/main/java/org/tools4j/nobark/run/ThreadLike.java b/src/main/java/org/tools4j/nobark/run/ThreadLike.java index 7e9231e..38d96ef 100644 --- a/src/main/java/org/tools4j/nobark/run/ThreadLike.java +++ b/src/main/java/org/tools4j/nobark/run/ThreadLike.java @@ -1,7 +1,7 @@ /** * The MIT License (MIT) * - * Copyright (c) 2018 nobark (tools4j), Marco Terzer, Anton Anufriev + * Copyright (c) 2019 nobark (tools4j), Marco Terzer, Anton Anufriev * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/org/tools4j/nobark/run/ThreadState.java b/src/main/java/org/tools4j/nobark/run/ThreadState.java index 4154368..31c82c6 100644 --- a/src/main/java/org/tools4j/nobark/run/ThreadState.java +++ b/src/main/java/org/tools4j/nobark/run/ThreadState.java @@ -1,7 +1,7 @@ /** * The MIT License (MIT) * - * Copyright (c) 2018 nobark (tools4j), Marco Terzer, Anton Anufriev + * Copyright (c) 2019 nobark (tools4j), Marco Terzer, Anton Anufriev * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/java/org/tools4j/nobark/run/package-info.java b/src/main/java/org/tools4j/nobark/run/package-info.java index 3fdfca0..7f46a93 100644 --- a/src/main/java/org/tools4j/nobark/run/package-info.java +++ b/src/main/java/org/tools4j/nobark/run/package-info.java @@ -1,7 +1,7 @@ /** * The MIT License (MIT) * - * Copyright (c) 2018 nobark (tools4j), Marco Terzer, Anton Anufriev + * Copyright (c) 2019 nobark (tools4j), Marco Terzer, Anton Anufriev * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/test/java/org/tools4j/nobark/run/ShutdownableThreadTest.java b/src/test/java/org/tools4j/nobark/run/ShutdownableThreadTest.java index f0a3c46..657aaf4 100644 --- a/src/test/java/org/tools4j/nobark/run/ShutdownableThreadTest.java +++ b/src/test/java/org/tools4j/nobark/run/ShutdownableThreadTest.java @@ -55,6 +55,13 @@ private static RunnableFactory loopUntil(final BooleanSupplier loopCondition) { }; } + private static RunnableFactory loopForMillis(final long millis) { + return run -> () -> { + final long endTime = System.currentTimeMillis() + millis; + while (System.currentTimeMillis() < endTime); + }; + } + @Test public void shutdown() { //given @@ -185,15 +192,13 @@ public void awaitTermination() { } @Test - public void awaitTimeout_zeroWaitsNotAtAll() { + public void awaitTimeout_zeroWaitsForever() { //given - final Shutdownable thread = ShutdownableThread.start(LOOP_WHILE_RUNNING, LOOP_ONCE, Thread::new); + final Shutdownable thread = ShutdownableThread.start(loopForMillis(500), LOOP_ONCE, Thread::new); //when + then - assertFalse(thread.awaitTermination(0, TimeUnit.SECONDS)); - assertFalse(thread.isTerminated()); - - thread.shutdownNow(); + assertTrue(thread.awaitTermination(0, TimeUnit.SECONDS)); + assertTrue(thread.isTerminated()); } @Test