温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java中for(;;)和while(true)的区别是什么

发布时间:2021-11-25 13:13:14 来源:亿速云 阅读:174 作者:柒染 栏目:开发技术

今天就跟大家聊聊有关Java中for(;;)和while(true)的区别是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

    1、问题来源

    在阅读JavaJDK源码时,发现大部分写源码的大佬多采用for(;;)的方式来死循环,比如说AQS(AbstractQueuedSynchronizer)中大量使用的自旋的方式获取共享状态。

    /**
    
     * 通过“死循环”的方式来正确的添加节点
    
     */
    
    private Node enq(final Node node) {
    
        // 不断循环,直至CAS插入节点成功
    
        for (;;) {
    
            Node t = tail;
    
            if (t == null) { 
    
                // 当尾节点为null,此时需要初始化头节点和尾节点
    
                if (compareAndSetHead(new Node()))
    
                    tail = head;
    
            } else {
    
                // 插入节点前驱节点指向原先尾节点
    
                node.prev = t;
    
                // CAS插入至同步队列的尾节点
    
                if (compareAndSetTail(t, node)) {
    
                    t.next = node;
    
                    return t;
    
                }
    
            }
    
        }
    
    }
    /**
    
     * “死循环”获取同步状态,并且当前仅当前驱节点是头节点是才能够尝试获取同步状态
    
     */
    
    final boolean acquireQueued(final Node node, int arg) {
    
        boolean failed = true;
    
        try {
    
            boolean interrupted = false;
    
            // 不断循环
    
            for (;;) {
    
                // 获取当前节点的前驱节点,如果前驱节点为null将会抛出空指针异常
    
                final Node p = node.predecessor();
    
                // 如果当前节点的前驱节点是头节点,尝试获取同步状态
    
                if (p == head && tryAcquire(arg)) {
    
                    // 设置当前节点为头节点,并且将节点线程和节点的前驱节点置为null,help GC
    
                    setHead(node);
    
                    p.next = null; // help GC
    
                    failed = false;
    
                    return interrupted;
    
                }
    
                // 如果不符合条件,则判断当前节点前驱节点的waitStatus状态来决定是否需要挂起LockSupport.park(this);
    
                if (shouldParkAfterFailedAcquire(p, node) &&
    
                    parkAndCheckInterrupt())
    
                    interrupted = true;
    
            }
    
        } finally {
    
            // 失败则取消
    
            if (failed)
    
                cancelAcquire(node);
    
        }
    
    }

    2、比较

    Java代码在编译后都会装换为虚拟机可以识别的字节码,我们通过编译器对两者生成的字节码从原理是来观察两者的区别

    2.1 测试代码for

    package com.liziba.jsw;
    
    /**
    
     * <p>
    
     *		for死循环测试
    
     * </p>
    
     *
    
     * @Author: Liziba
    
     * @Date: 2021/6/21 11:36
    
     */
    
    public class Test {
    
    
    
        private static void m1() {
    
            for (;;) {
    
    
    
            }
    
        }
    
        
    
    }

    通过 javap -v Test.class查看生成的字节码(只截取关键部分)

    Java中for(;;)和while(true)的区别是什么

    2.2 测试代码while

    package com.liziba.jsw;
    
    
    
    /**
    
     * <p>
    
     *		while死循环测试
    
     * </p>
    
     *
    
     * @Author: Liziba
    
     * @Date: 2021/6/21 11:36
    
     */
    
    public class Test {
    
        
    
        private static void m2() {
    
            while (true){
    
    
    
            }
    
        }
    
        
    
    }

    通过 javap -v Test.class查看生成的字节码(只截取关键部分)

    3、结论

    for死循环和while死循环编译后的字节码(编译器是可以做优化的),完全一模一样,所以两者在使用过程中,其实是没有任何区别。看到这里是不是有点生气,但是又想问问什么源码那些大佬写代码基本上不用while(true),我想主要原因还是早期C语言中for(;;)循环和while(1)编译生成的字节码不一样,for(;;)生成的字节码明显更加少,一定程度上能节省一些内存空间。所以很多java大佬,也是精通各种其他语言的,因此写法习惯也就延续下来了吧。再者,我在查阅资料的时候也看到有笔者验证早期的Java编译器对for死循环编译生成的字节码也是少于while死循环编译后生成的字节码,可能随着编译器优化能力不断的增强,现在这两者在目前广泛使用的编译器中已经没有什么区别了。

    看完上述内容,你们对Java中for(;;)和while(true)的区别是什么有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    AI