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

目录
  • 1、问题来源
  • 2、比较
    • 2.1 测试代码for
    • 2.2 测试代码while
  • 3、结论

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查看生成的字节码(只截取关键部分)

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死循环编译后生成的字节码,可能随着编译器优化能力不断的增强,现在这两者在目前广泛使用的编译器中已经没有什么区别了。

到此这篇关于 Javafor(;;)while(true)的区别的文章就介绍到这了,更多相关for(;;)while(true)的区别内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2021-11-24

Java中while语句的简单知识及应用

先谈谈while循环的三要素 while循环的三要素:(1)初始化变量(2)循环条件(3)改变循环变量的值 当你要用while循环时主要知道这三个要素什么,那么循环起来就得心应手了. 下面是while循环语法和特点: while语句的形式 while(条件表达式)//循环条件 { 语句序列//循环体 } while语句的执行过程: ① 先计算条件表达式的值 : ② 如果该表达式的值为true,则执行循环体的语句: ③ 如果表达式的值为false,退出循环,不再执行 循环体,结束while语句的执

Java While循环 do-while循环用法

循环语句就是让计算机根据条件做循环计算,在条件满足时继续循环,条件不满足时退出循环. Java提供了while条件循环.它的基本用法是: while (条件表达式) { 循环语句 } // 继续执行后续代码 while循环在每次循环开始前,先会判断条件是否成立.如果计算结果为true,就把循环体内的语句执行一遍,如果计算结果为false,那就直接跳到while循环的末尾,继续往下执行. do while循环的基本结构 do{ //循环体 }while(条件); 与while不同的是,do whi

Java中使用While语句自增运算遍历数组典型实例

public class BirdArray { public static void main(String args[]){ String[] str = new String[]{"麻雀","老鹰","白鸽","黄雀","百灵鸟","孔雀","鹦鹉","丹顶鹤"}; int index =0; //创建索引变量 System.out.prin

详解Java中的do...while循环语句的使用方法

对于while语句而言,如果不满足条件,则不能进入循环.但有时候我们需要即使不满足条件,也至少执行一次. do-while循环和while循环相似,不同的是,do-while循环至少会执行一次. do { //代码语句 }while(布尔表达式); do..while循环语句也称为后测试循环语句,它的循环重复执行方式,也是利用一个条件来控制是否要继续重复执行这个语句.与while循环所不同的是,它先执行一次循环语句,然后再去判断是否继续执行.例如,计算1到100之间所有整数的和,也可以使用do.

Java while(scanner.hasNext())无法跳出的解决方案

目录 Java while(scanner.hasNext())无法跳出 情况说明: 原因: 解决方案: java 的while+hasNext() Java while(scanner.hasNext())无法跳出 情况说明: 该问题是在做PAT乙级1010时遇到的,我需要在键盘读入有限个数,然后两两进行计算.我一开始想的是声明一个数组,将所有读入的数字进行保存,再分别计算,但是我发现他并不会跳出我设的循环,而是一直在执行 当读入最后一个数据的时候,并不是跳出,而是阻塞在了while中,一直执

举例讲解Java中do-while语句的使用方法

在学习 do/while 语句之前,先清楚 while 语句是如何工作的.while 语句是先进行条件判断,再执行大括号内的循环体. do/while 语句与 while 语句不同的是,它先执行大括号内的循环体,再判断条件,如果条件不满足,下次不在执行循环体.也就是说,在判断条件之前,就已经执行大括号内的循环体. 示例:计算1+2+3+4......+100的结果. public class control5{ public static void main(String[] args){ in

Java中for、while、do while三种循环语句的区别介绍

本文通过实例讲解给大家介绍Java中for.while.do while三种循环语句的区别,具体详情如下所示: 第一种:for循环 循环结构for语句的格式: for(初始化表达式;条件表达式;循环后的操作表达式) { 循环体; } eg: class Dome_For2{ public static void main(String[] args) { //System.out.println("Hello World!"); //求1-10的偶数的和 int sum = 0; fo

Java基础入门篇——While循环

循环结构分两大类,一类是当型,一类是直到型. 当型: 当布尔值表达式条件为True时,反复执行某语句,当布尔表达式的值为False时才停止循环,例如:while 与 for循环. 直到型: 先执行某语句,在判断布尔表达式,如果为true,再执行某语句,如此反复,直到布尔表达式条件为false时才停止循环,例如do - while循环. 语法结构: while (布尔表达式) { 循环体; } 一.循环结构语句 1.在我们实际生活中经常会把同一件事情重复做好几次.例如:潮汕人喜欢喝茶,只要在喝茶的

零基础入门篇之Linux及Arm-Linux程序开发笔记

前言:本文记录了自己从一个完全不懂Linux的人如何一步步学会Linux程序开发的过程.当然也希望本文能够达到它的目的,让那些和我一样没有任何基础的人也能快速入门Linux程序开发. 一.Arm-Linux程序开发平台简要介绍 Arm-Linux程序的开发并不像我们以前接触的Windows程序开发那样,关于平台的搭建就繁琐很多,所以在正式进入程序开发之前先对这种开发模式进行简要介绍,让一个即使没有任何Linux开发经验的程序员也能够看懂后面的内容. 1.1程序开发所需系统及开发语言 开发arm-

jquery 常用操作整理 基础入门篇

jQuery由美国人John Resig创建,至今已吸引了来自世界各地的众多javascript高手加入其team,包括来自德国的Jörn Zaefferer,罗马尼亚的Stefan Petre等等. jQuery是继prototype之后又一个优秀的Javascrīpt框架.其宗旨是--WRITE LESS,DO MORE,写更少的代码,做更多的事情. 它是轻量级的js库(压缩后只有21k) ,这是其它的js库所不及的,它兼容CSS3,还兼容各种浏览器 (IE 6.0+, FF 1.5+, S

教大家8天学通MongoDB——第一天 基础入门篇

关于mongodb的好处,优点之类的这里就不说了,唯一要讲的一点就是mongodb中有三元素:数据库,集合,文档,其中"集合" 就是对应关系数据库中的"表","文档"对应"行". 一: 下载 上MongoDB官网 ,我们发现有32bit和64bit,这个就要看你系统了,不过这里有两点注意: ①:根据业界规则,偶数为"稳定版"(如:1.6.X,1.8.X),奇数为"开发版"(如:1.7.X

JavaScript_object基础入门(必看篇)

之前写Java时老是有点蒙,大部分都是用jQuery,但原理还不是很清楚,最近一段时间在系统的学习JavaScript,有什么问题或错误请指出,多谢..................... Object所有类的基础类 var obj = new Object(); var obj = {}; //实例化对象 给对象设置属性分为两种: 1.使用直接量的方式:对象.属性/方法,这种方式直观.易懂 obj.name = '张三'; obj.age = 20; obj.sex = '男'; obj.s

java基础之数组常用操作总结(必看篇)

常用的对数组进行的操作 1.求数组中最大值,最小值 思路:假设下标为0的元素是最大值,遍历数组,依次跟max进行比较,如果有元素比这个max还大,则把这个值赋给max.最小值同样 public class TestArray{ public static void main(String[] args){ int[] arr={23,45,234,576,34,87,34,12,67}; int max=arr[0]; int min=arr[0]; for(int i=0;i<arr.leng

Java基础篇_有关接口和抽象类的几道练习题(分享)

呃,一定要理解之后自己敲!!!这几道题,使我进一步了解了接口和抽象类. 1.设计一个商品类 字段: 商品名称,重量,价格,配件数量,配件制造厂商(是数组,因为可能有多个制造厂商) 要求: 有构造函数 重写 toString 方法 重写 equals方法,进行两件商品的比较 package TT; import java.util.Arrays; public class G { private int 重量; private String 商品名称; private int 价格; privat

详解Java基础篇--面向对象1(构造方法,static、this关键字)

面向对象,面向过程的区别.拿下五子棋来说: 面向过程分析: 开始游戏 黑棋先走 绘制画面 判断输赢 轮到白棋 绘制画面 判断输赢 返回步骤2 输出结果 面向对象分析: 黑白双方,双方行为是一模一样的 棋盘系统,负责绘制画面 规则系统,判断犯规.输赢 传统的面向过程编程是思考问题的解决步骤,这种思维方式适用于问题规模较小时.可是当问题规模大,要求程序有更好的可扩展性,能更快速地查错时面向对象设计思想就能体现出其优势.面向对象更接近人类地自然思维方式,将现实世界中的事物抽象为对象和对象的方法. 面向

Java基础之打印万年历的简单实现(案例)

问题:输入年,月,打印对应年月的日历. 示例: 问题分析: 1,首先1970年是Unix系统诞生的时间,1970年成为Unix的元年,1970年1月1号是星期四,现在大多的手机的日历功能只能显示到1970年1月1日这一天; 2,要想打印某年某月的日历,首先应该计算出这个月1号是星期几? 解决1号是星期几? 2.1:先计算出年天数,即截至这一年1月1号的天数,用for循环,从1970年开始,闰年+366,平年+365; 2.2:计算出月天数,即截至本月1号的天数,用for循环,从1月份开始,算出月

Bootstrap零基础入门教程(三)

什么是 Bootstrap? Bootstrap 是一个用于快速开发 Web 应用程序和网站的前端框架.Bootstrap 是基于 HTML.CSS.JAVASCRIPT 的. 历史 Bootstrap 是由 Twitter 的 Mark Otto 和 Jacob Thornton 开发的.Bootstrap 是 2011 年八月在 GitHub 上发布的开源产品. 写到这里,这篇从零开始学Bootstrap(3)我想写以下几个内容: 1. 基于我对Bootstrap的理解,做一个小小的总结.

spring boot 学习笔记(入门篇)

简介: Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.用我的话来理解,就是spring boot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架(不知道这样比喻是否合适). 优点: 其实就是简单.快速.方便!平时如果我们需要搭建一个spring web项目的时候需要怎么