玩碎Java之new Thread与completableFuture竟然结果不一样

现象

public static void main(String[] args) throws InterruptedException {

        CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(1000);
                System.out.println("ddd");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        System.out.println("ccc");
    }
public static void main(String[] args) throws InterruptedException {

        new Thread(() -> {
            try {
                Thread.sleep(1000);
                System.out.println("ddd");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }).start();

        System.out.println("ccc");
//        Thread.sleep(2);
    }

大家想想以上2段代码的输出都是什么呢?是一样的么?
结果,
代码1,输出:

ccc

代码2,输出:

ccc
ddd

科学吗?不应该一样吗?

原因

new Thread

当JVM启动时,通常有一个非守护的线程(它通常调用某个指定类的main方法)。JVM 继续执行线程,直到发生以下任何一种情况时停止:

  • Runtime 类的 exit 方法已被调用,且安全管理器已允许执行退出操作(比如调用 Thread.interrupt 方法)
  • 不是守护线程的所有线程都已死亡,要么从对 run 方法的调用返回,要么抛出一个在 run 方法之外传播的异常

new Thread是非守护线程,所以要等new Thread执行完成,JVM才会停止。

completableFuture

completableFuture是守护线程。
那么为什么内部创建的线程completableFuture是守护线程呢?
因为CompletableFuture.supplyAsync是由内部管理的ForkJoinPool。默认行为ForkJoinPool是创建守护线程。

对于守护线程,除非join()方法被调用,否则主线程永远不会等待它们完成,所以以上例子中,主线程先结束,其他线程仍在运行,但不会在控制台上打印任何内容。

可以使用以下方法控制线程各自的行为:
public final boolean isDaemon()
public final void setDaemon(boolean on)

所以,才出现了以上2种不一样的结果。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值