system.nanoTime()错误吗?

时间:2019-06-09 00:20:00

标签: java time

我正在编写一个FTP客户端应用程序,并在代码的两点使用了System.nanoTime(),以秒为单位的差返回18,而我的程序仅用了2秒钟...检查onPostExecute方法中的日志... 为什么会发生这种情况,我该如何解决?

protected String doInBackground(String... urls)
{
    try
        {
        if(perflag)
            return "Not yet";
        String ipadd= ip.getText().toString();
            BufferedReader br;
            int port =Integer.parseInt(portt.getText().toString());
        while(true) {
            socket = new Socket(ipadd, port);
            //Button conn=(Button) findViewById(R.id.connectb);
            if(startflag)
            {
                starttime=System.nanoTime();
                startflag=false;
            }
            //conn.setEnabled(false);
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            BufferedOutputStream bo = new BufferedOutputStream(socket.getOutputStream());
            PrintWriter pw = new PrintWriter(bo, true);
            file = br.readLine();
            if (file.equals("Finished"))
            {
               // socket.close();
                Log.i("stat","above sock");
               // Thread.sleep(1000);
                //socket= new Socket(ipadd,port);
                //br= new BufferedReader(new InputStreamReader(socket.getInputStream()));
                datas=br.readLine();
                data=Double.parseDouble(datas);
                Log.i("stat",datas);
                br.close();
                socket.close();
                finflag=true;
                break;
            }
            File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);
            File f = new File(path, "/" + file);
            byte[] buff = new byte[1024];
            int len;

            int i=0;
            while(f.exists())
            {
                f= new File(path,"/"+"("+i+")"+file);
                i++;
            }
            pw.println("done");
            DataInputStream is = new DataInputStream(socket.getInputStream());
            FileOutputStream fos = new FileOutputStream(f);
            publishProgress(file);

            while ((len = is.read(buff)) != -1) {


                fos.write(buff, 0, len);

            }

            publishProgress(file);
        }
    }catch(NumberFormatException nfe)
    {

        runOnUiThread(new Runnable() {
            public void run() {
                Toast.makeText(MainActivity.this,"Enter a proper IP and port!",Toast.LENGTH_LONG).show();
                start();
            }
        });
        nfe.printStackTrace();

    }
    catch(java.net.UnknownHostException un)
    {
        runOnUiThread(new Runnable() {
            public void run() {
                Toast.makeText(MainActivity.this,"Enter a proper IP and port!",Toast.LENGTH_LONG).show();
                start();
            }
        });
        //Toast.makeText(MainActivity.this,"Enter a proper IP and port!",Toast.LENGTH_LONG).show();
        un.printStackTrace();
    }
    catch(java.net.NoRouteToHostException no)
    {

        runOnUiThread(new Runnable() {
            public void run() {
                Toast.makeText(MainActivity.this,"There is no active server at the specified IP and port!",Toast.LENGTH_LONG).show();
                start();
            }
        });
        no.printStackTrace();
    }
    catch(Exception e)

    {
            Log.i("error",e.getMessage());
            runOnUiThread(new Runnable() {
                public void run() {
                    Toast.makeText(MainActivity.this, "Error occurred!Try checking storage permissions or connection.", Toast.LENGTH_LONG).show();

                    start();
                }
            });
        e.printStackTrace();
    }

    endtime=System.nanoTime();
    return "Not Yet";
}
protected void onProgressUpdate(String... para)
{
    super.onProgressUpdate(para);
    trans.setText("Transfering file: "+para[0]);
}
protected void onPostExecute(String as) {
    start();

    if(finflag)
    {
        startflag=true;
        Log.i("start",String.valueOf(starttime));
        Log.i("end",String.valueOf(endtime));
        totaltime=endtime-starttime;

        Log.i("total",String.valueOf(totaltime));
        //totaltime/=100000000;
        double time=totaltime/1000000000;
        Log.i("time in secs",String.valueOf(time));
        double rate= (double)(data/time);
        Toast.makeText(MainActivity.this,"Transfer successful!",Toast.LENGTH_LONG).show();
        Toast.makeText(MainActivity.this,"Average transfer rate: "+rate+"MBps",Toast.LENGTH_LONG).show();
        finflag=false;
    }
}

2 个答案:

答案 0 :(得分:2)

进行整数除法以获取秒是没有意义的,因为那只会返回整秒。您无需整秒钟使用nanoTime。更改:

double time=totaltime/1000000000;

收件人

double time=totaltime/1000000000d; // (or totaltime/1000000000.0)

但是您使用的除数很好; nano是10 -9 。但是,我在您的部门上方的代码中看到一条注释掉的行:

        //totaltime /= 100000000;
double time=totaltime/1000000000;

在该行中,除数只有8个零,没有9个零。您确定发布的“ 18”秒来自double time=totaltime/1000000000;而非totaltime /= 100000000;吗?因为如果除数中的零个太少,则实际的1.8秒时间看起来像18秒。

正如评论员所提到的那样,问题实际上是魔术常数,该常数很容易获得错误的零。

以下是解决此问题的几种方法:

  • Java允许您出于任何原因在下划线中添加下划线;您可以编写totaltime / 1_000_000_000d使其更清楚地显示您正在使用多少个零。
  • Java还允许将科学符号表示为双精度,因此您也可以编写totaltime / 1e9
  • Java内置了用于转换时间单位的函数;但是,由于只需要几分之一秒,因此不能简单地说出TimeUnit.NANOSECONDS.toSeconds(totaltime)(这将舍入到1秒)。但是,您可以说totaltime / (double) TimeUnit.SECONDS.toNanos(1)

答案 1 :(得分:0)

tl; dr

Duration                          // Represent a span-of-time unattached to the timeline.
.ofNanos(                         // Represent a count of nanoseconds.
    System.nanoTime() - start     // Calculate elapsed nanoseconds.
)                                 // Returns a `Duration` object.
.toString()                       // Generates text in standard ISO 8601 format for elapsed time.
  

PT2.020615864S

Duration

我将使用Duration类。此类表示时间轴上未附加的时间跨度,其分辨率为hour-minutes-seconds-nanoseconds。

减去对nanoseconds的调用返回的System.nanoTime的两个计数。将结果传递到Duration.ofNanos

long start = System.nanoTime() ;
Thread.sleep( TimeUnit.SECONDS.toMillis( 2 ) ); 
long stop = System.nanoTime() ;

Duration d = Duration.ofNanos( stop - start ) ;

System.out.println( d ) ;

请参阅此code run live at IdeOne.com

  

PT2.020615864S

实际上,在真实代码中,我们需要处理Thread sleep被打断(唤醒)的情况。

long start = System.nanoTime();
try
{
    Thread.sleep( TimeUnit.SECONDS.toMillis( 2 ) ); 
} catch ( InterruptedException e )
{
    e.printStackTrace();
}
long stop = System.nanoTime();

Duration d = Duration.ofNanos( stop - start );

System.out.println( d );