System.nanoTime () не так? - PullRequest
       1

System.nanoTime () не так?

0 голосов
/ 09 июня 2019

Я пишу клиентское приложение 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 ]

2 голосов
/ 09 июня 2019

Нет смысла делать целочисленное деление, чтобы получить секунды, так как это вернет вам только целые секунды;вам не нужно использовать nanoTime в течение целых секунд.Измените:

double time=totaltime/1000000000;

На

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

Но используемый вами делитель в порядке;нано составляет 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)
0 голосов
/ 09 июня 2019

ТЛ; др

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. Этот класс представляет промежуток времени, не привязанный к временной шкале, в разрешении часы-минуты-секунды-наносекунды.

Вычтите два числа наносекунд , возвращаемых вызовами на 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 ) ;

См. код, запущенный в режиме реального времени на IdeOne.com .

PT2.020615864S

На самом деле, в реальном коде нам нужно обработать спящий поток с прерыванием (пробуждением).

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 );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...