debug和run运⾏结果不同的JAVA代码
测试环境如下:JAVA版本是11,IDE是IDEA2019.3.1的社区版本,操作系统是win10专业版。
程序要处理的是⼀个简单的算法课作业:
两重循环,迭代变量i,j每执⾏⼀次循环体则⾃增1,取值范围为0<=i<N以及0<=j<N,循环体内容任意,⽐如s=s+i-j;请记录下运⾏时间,输出当两重循环运⾏时间是0.1s, 1s, 10s时的N.
题⽬要求很简单,思路是每次都记录下循环时间,⽤⼆分法让程序⾃⼰出来这3个N。
以下是源码:
⼀个⼩⼯具类,⽤来输出结果到⽂本:
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class OutData
{
public OutData(Integer n1,//最接近0.1s的N
Integer n2,//最接近1s的N
Integer n3,//最接近10s的N
StringBuffer useTime1,//n1的具体时间
StringBuffer useTime2,//n2的具体时间
StringBuffer useTime3//n3的具体时间
)throws IOException
{
File fileOfDataIn =new File("");
FileWriter fileWriter;
if(!ists())
{
fileWriter =new Name(),true);
}else
{
fileWriter =new Name(),false);
fileWriter.write("");
}
fileWriter.write("N为:"+ n1.toString()+"时,所⽤时间为:"+ String()+"毫秒"
+"\n"+"N为:"+ n2.toString()+"时,所⽤时间为:"+ String()+"毫秒"
+"\n"+"N为:"+ n3.toString()+"时,所⽤时间为:"+ String()+"毫秒");
fileWriter.close();
}
}
接下来是main类,为了节省运⾏时间,求1s和10s的两次先注释掉:
import java.io.IOException;
//后来我的解决办法是再加⼀个随机函数到循环体⾥⾯,这⾥先注释掉
//import java.util.Random;
public class DoubleCirculationMain
{
public static void main(String[] args)throws IOException
{
int startN =1000;
StringBuffer useTime1 =new StringBuffer(),
useTime2 =new StringBuffer(),
useTime3 =new StringBuffer();
//使⽤⼆分法⾃动到⽤时分别接近0.1s、1s和10s的N值并输出
int n1 =getClosestValue(100, startN, useTime1);
int n2=0;//节省测试时间
//int n2 = getClosestValue(1000, n1, useTime2);
int n3=0;//节省测试时间
//int n3 = getClosestValue(10000, n2, useTime3);
new OutData(n1, n2, n3, useTime1, useTime2, useTime3);
}
}
private static int getClosestValue(int timeToApproach,int startN, StringBuffer useTimeBuffer) {
int nLower = startN,
increment =10000,
nHeigher = nLower + increment,
nMedian =(nHeigher + nLower)/2,
forCaculate =0;
long startTime, endTime, costime =0, costime2 =0;
//后来我的解决办法是再加⼀个随机函数到循环体⾥⾯,这⾥先注释掉
/
/Random random = new Random();
while(true)
{//循环⾄⽬标处于上下限区间内
nMedian =(nHeigher + nLower)/2;//刷新中位数
forCaculate =0;
startTime = System.currentTimeMillis();//开始计时
for(int i1 =0; i1 < nHeigher; i1++)
{
for(int i2 =0; i2 < nHeigher; i2++)
{
forCaculate = forCaculate + i1 - i2;
/
/后来我的解决办法是再加⼀个随机函数到循环体⾥⾯,这⾥先注释掉
//forCaculate = forCaculate + i1 - Int(100);
}
}
endTime = System.currentTimeMillis();//结束计时
//⼀开始就防着JAVA虚拟机⾃动优化代码,所以故意调⽤次运⾏结果
System.out.println(forCaculate);
costime = endTime - startTime;
if(costime < timeToApproach)
{//如果上限⼩于⽬标,则下限取该值,然后上限增⼤。
nHeigher += increment;
nLower = nHeigher;
}else
{//如果上限⼤于⽬标,则退出循环,花费时间值是上限时间
break;
}
}
while(costime >=1.01* timeToApproach && nHeigher - nLower >1)
{//当花费时间超出1.01倍⽬标且上下限差距⼤于1时,继续逼近
nMedian =(nHeigher + nLower)/2;//刷新中位数。
startTime = System.currentTimeMillis();//开始计时
for(int i1 =0; i1 < nMedian; i1++)
{
for(int i2 =0; i2 < nMedian; i2++)
{
forCaculate = forCaculate + i1 - i2;
//后来我的解决办法是再加⼀个随机函数到循环体⾥⾯,这⾥先注释掉
//forCaculate = forCaculate + i1 - Int(100);
}
}
endTime = System.currentTimeMillis();//结束计时
//还是为了防着JAVA虚拟机⾃动优化代码,所以故意调⽤次运⾏结果
System.out.println(forCaculate);
costime2 = endTime - startTime;
if(costime2 > timeToApproach)
小白学java有前途吗{//如果中位数也⼤于⽬标,则中位数变为新上限,上限花费时间更新
nHeigher = nMedian;
costime = costime2;
}else
{//如果中位数⼩于⽬标,则中位数变成新下限
nLower = nMedian;
}
}
useTimeBuffer.append(costime);//输出逼近处理后的上限时间
useTimeBuffer.append(costime);//输出逼近处理后的上限时间
return nHeigher;
}
}
run输出的⽂本内容是:
在getClosestValue()⽅法中随意加个断点debug之后输出的⽂本内容是:
⾸先,我已经反复确认⼏遍了,这个问题确实存在,rebuild也好,完全重启IDEA也好,重启windows也好,run和debug的结果就是不⼀样。
其次,如果把断点加在main⽅法⾥,则debug的运⾏结果会和run是⼀样的,但是如果随意在⼆分法⽅法getClosestValue()中加断点就会出现debug的运⾏结果和run不同的问题,debug的结果是理论上应该得到的结果。
发现这个问题之后,直觉让我在循环体⾥加⼊⼀个随机过程,因为我怀疑在解释运⾏时,编译器判断出了两个重复的代码段,于是就直接调⽤了运⾏结果以优化程序的运⾏效率,或许这就是JAVA在执⾏重复调⽤的代码段时效率可以追上C++的秘诀吧。不过如果真的是这样的话,显然这忽略了我在程序运⾏时间上的验证性要求,最后导致了输出结果和理论不⼀样,所以我⼀往循环体⾥加⼊随机过程之
后,debug和run的结果就统⼀的符合程序的理论结果了。
另⼀个值得⼀提的奇怪现象是,在我每次测试完这段代码之后,如果此时关闭idea,则下次打开idea⼀定会在开始的时候卡住,但是重启windows之后idea⼜可以正常打开,所以这个问题可能和idea有关?JAVA IDE我⼀直⽤的是IntelliJ IDEA,虽然在刚开始学习JAVA的时候我就遇到过⼀次,不过当时没有注意把问题记录下来,和⽼师说了之后也只能不了了之。这次我⼜遇到了这样的问题,不得不说还是很吓⼈的,毕竟如果连debug⼯具都不能相信了那我们⼜该相信谁。
作为⼀个⼩⽩,⽬前不太想过于深究,因为问题可能出现的地⽅太多了,⽽我现在也整不明⽩,所以姑且先记在这⾥,如果有路过的朋友对这个问题有兴趣,可以在评论区说说⾃⼰的看法,或者可以⾃⼰试⼀下。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。