Skip to content

Instantly share code, notes, and snippets.

@volyx
Created February 22, 2020 20:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save volyx/6f231b00820bede9a73896ded69a3029 to your computer and use it in GitHub Desktop.
Save volyx/6f231b00820bede9a73896ded69a3029 to your computer and use it in GitHub Desktop.
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class Test {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private static final AtomicInteger threadNumber = new AtomicInteger(1);
private static final ScheduledThreadPoolExecutor executor = useDaemonThreadFactory(new ScheduledThreadPoolExecutor(1));
public static void main(String[] args) throws InterruptedException, IOException {
executor.execute(() -> {
System.out.println("start " + ProcessHandle.current().pid());
while (true);
});
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.out.println("start hook");
shutdownAndAwaitTermination(executor, 30, TimeUnit.SECONDS);
System.out.println("end hook");
}));
Thread.sleep(5000);
new ProcessBuilder("kill", "-15", Long.toString(ProcessHandle.current().pid())).start();
}
public static ScheduledThreadPoolExecutor useDaemonThreadFactory(ScheduledThreadPoolExecutor executor) {
executor.setThreadFactory(r -> {
SecurityManager s = System.getSecurityManager();
ThreadGroup group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
String namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-";
Thread t = new Thread(group, r,namePrefix + threadNumber.getAndIncrement(),0);
// t.setDaemon(Boolean.parseBoolean("daemon"));
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
});
return executor;
}
/**
* Shuts down the given executor service gradually, first disabling new submissions and later, if
* necessary, cancelling remaining tasks.
*
* <p>The method takes the following steps:
* <ol>
* <li>calls {@link ExecutorService#shutdown()}, disabling acceptance of new submitted tasks.
* <li>awaits executor service termination for half of the specified timeout.
* <li>if the timeout expires, it calls {@link ExecutorService#shutdownNow()}, cancelling pending
* tasks and interrupting running tasks.
* <li>awaits executor service termination for the other half of the specified timeout.
* </ol>
*
* <p>If, at any step of the process, the calling thread is interrupted, the method calls
* {@link ExecutorService#shutdownNow()} and returns.
*
* @param service the {@code ExecutorService} to shut down
* @param timeout the maximum time to wait for the {@code ExecutorService} to terminate
* @param unit the time unit of the timeout argument
* @return {@code true} if the {@code ExecutorService} was terminated successfully, {@code false}
* if the call timed out or was interrupted
* @since 17.0
*/
public static boolean shutdownAndAwaitTermination(
ExecutorService service, long timeout, TimeUnit unit) {
long halfTimeoutNanos = unit.toNanos(timeout) / 2;
// Disable new tasks from being submitted
System.out.println("start shutdown " + service.getClass());
service.shutdown();
try {
// Wait for half the duration of the timeout for existing tasks to terminate
if (!service.awaitTermination(halfTimeoutNanos, TimeUnit.NANOSECONDS)) {
// Cancel currently executing tasks
System.out.println("start shutdownNow " + service.getClass());
service.shutdownNow();
// Wait the other half of the timeout for tasks to respond to being cancelled
service.awaitTermination(halfTimeoutNanos, TimeUnit.NANOSECONDS);
}
System.out.println("end shutdown " + service.getClass());
} catch (InterruptedException ie) {
// Preserve interrupt status
// Thread.currentThread().interrupt();
System.err.println(ie.getMessage());
// (Re-)Cancel if current thread also interrupted
service.shutdownNow();
}
return service.isTerminated();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment