Java守护线程普通线程的例子

我们一般创建的线程都是普通非守护线程,守护线程是为普通线程服务的。这个说法比较抽象。

具体一个很大的区别是:

  • JVM中所有的线程都是守护线程的时候,JVM就可以退出了--JVM不会等待守护线程是否运行结束
  • 如果还有一个或以上的非守护线程则不会退出

非守护线程例子

    public static void main(String[] args) throws Exception {
        Thread runnableThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("in runnable demo");
            }
        });
        runnableThread.start();
        System.out.println("in main");
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                System.out.println("JVM Exit!");
            }
        });
    }

执行结果

in main
in runnable demo
JVM Exit!

可以看到,以为runnableThread默认是普通非守护线程,jvm必须等待他运行结束后才会关闭。

守护线程例子

setDaemon为true,就把线程设置成了守护线程。

  public static void main(String[] args) throws Exception {
        Thread runnableThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("in runnable demo");
            }
        });
        runnableThread.setDaemon(true);
        runnableThread.start();
        System.out.println("in main");
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                System.out.println("JVM Exit!");
            }
        });
    }

执行结果

in main
JVM Exit!

可以看到,jvm没有等待守护线程执行完毕就做了关闭。当主线程结束时,守护线程自动关闭,就免去了还要继续关闭子线程的麻烦,如:Java垃圾回收线程就是一个典型的守护线程。

额外一个例子

  public static void main(String[] args) throws Exception {
        ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
        CompletableFuture.supplyAsync(() ->
        {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                executor.shutdownNow();
            }
            System.out.println("in CompletableFutureDemo 1 ");
            return "ddd";
        }, executor);

        System.out.println("in main");
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                System.out.println("JVM Exit!");
            }
        });
    }

执行结果

in main
in CompletableFutureDemo 1 
JVM Exit!

删除外部传入的executor,用默认的executor

  public static void main(String[] args) throws Exception {
        //  ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
        CompletableFuture.supplyAsync(() ->
        {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("in CompletableFutureDemo 1 ");
            return "ddd";
        });

        System.out.println("in main");
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                System.out.println("JVM Exit!");
            }
        });
    }

执行结果

in main
JVM Exit!

当我们移除自定义的executor后发现jvm没有等待我们的子线程运行结束就直接关闭了。

以为默认的CompletableFuture使用的是守护线程池。

   public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
        return asyncSupplyStage(asyncPool, supplier);
    }

 

posted @ 2020-07-06 19:42  ibrake  阅读(374)  评论(0编辑  收藏  举报