import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import sun.misc.Signal; import sun.misc.SignalHandler; public class JavaStopGraceFully { public static int len = 5; static ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(1000); static ExecutorService executorService = Executors.newFixedThreadPool(3); static volatile AtomicBoolean stopPut = new AtomicBoolean(false); static volatile AtomicBoolean stopPoll = new AtomicBoolean(false); static volatile AtomicBoolean readyExitFlag = new AtomicBoolean(false); public static void main(String[] args) throws InterruptedException { executorService.submit(new Runnable() { @Override public void run() { while (true) { for (int i = 0; i < len + 1; i++) { try { queue.put(i); } catch (InterruptedException e) { e.printStackTrace(); } } try { TimeUnit.SECONDS.sleep(len); } catch (InterruptedException e) { e.printStackTrace(); } if (stopPut.get()) { break; } } System.out.println("exit put thread."); } }); executorService.submit(new Runnable() { @Override public void run() { while (true) { Integer ele = queue.poll(); System.out.println(ele); try { TimeUnit.SECONDS.sleep(1L); } catch (InterruptedException e) { e.printStackTrace(); } if (stopPoll.get()) { break; } } System.out.println("exit poll thread."); } }); executorService.submit(new Runnable() { @Override public void run() { while (true) { if (!stopPut.get()) { continue; } if (stopPut.get()) { if (0 == queue.size()) { stopPoll.set(true); readyExitFlag.set(true); } } if (readyExitFlag.get()) { break; } try { TimeUnit.SECONDS.sleep(1L); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("exit loop thread."); if (readyExitFlag.get()) { System.out.println("exit gracefully."); System.exit(0); } } }); SignalHandler sh = new SignalHandler() { @Override public void handle(Signal signal) { System.out .println(signal.getName() + ".." + signal.getNumber()); if (signal.getName().equals("INT") || signal.getName().equals("TERM")) { if (readyExitFlag.get()) { System.out.println("exit gracefully."); System.exit(0); } else { if (stopPut.get()) { System.out.println("wait for pop done."); } else { stopPut.set(true); } } } } }; Signal.handle(new Signal(System.getProperties().getProperty("os.name") .toLowerCase().startsWith("win") ? "INT" : "TERM"), sh); } }