Java
 Computer >> コンピューター >  >> プログラミング >> Java

Javaで経過時間・実行時間を計測する6つの方法を徹底解説

アプリケーションのパフォーマンスチューニングでは、特定の処理がどれだけの時間で完了するのかを正確に把握することが重要です。

一般的に経過時間(実行時間)とは、イベントの開始時点から終了時点までの時間のことを指します。Javaでは、標準ライブラリや外部ライブラリを活用することで、さまざまな手法で実行時間を計測できます。

Javaで経過時間を計測する主な方法

  • System.currentTimeMillis():現在の時刻をミリ秒単位で返します。処理の実行前後で時刻を取得し、その差分から経過時間を求めます。
  • System.nanoTime():現在の時刻をナノ秒単位で返します。より高精度な計測が必要な場合に適しています。
  • Instantクラスのnow()メソッド:現在時刻を取得し、Duration.between()メソッドと組み合わせることで2つの時刻の差分を求められます。
  • Apache CommonsのStopWatchクラス:start()、stop()、getTime()というメソッドを提供しており、ストップウォッチのように直感的に計測できます。
  • java.util.DateクラスのgetTime()メソッド:現在の時刻をミリ秒で返します。こちらも差分方式で経過時間を算出します。
  • CalendarクラスのgetInstance().getTime().getTime():現在の時刻を取得し、差分から経過時間を求めることができます。

例1:System.currentTimeMillis()を使う方法

public class Example {
    public void test(){
        int num = 0;
        for(int i=0; i<=50; i++){ 
            num = num+i;
            System.out.print(num+", ");
        } 
    }
    public static void main(String args[]){ 
        // 開始時刻を取得
        long begin = System.currentTimeMillis();
        // 計測対象の処理を実行
        new Example().test();
        // 終了時刻を取得
        long end = System.currentTimeMillis();

        long time = end-begin;
        System.out.println();
        System.out.println("Elapsed Time: "+time +" milli seconds");
    }
}

出力結果

0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231, 253, 276, 300, 325, 351, 378, 406, 435, 465, 496, 528, 561, 595, 630, 666, 703, 741, 780, 820, 861, 903, 946, 990, 1035, 1081, 1128, 1176, 1225, 1275,
Elapsed Time: 4 milli seconds

例2:System.nanoTime()を使う方法

public class Example {
    public void test(){
        int num = 0;
        for(int i=0; i<=50; i++){ 
            num = num+i;
            System.out.print(num+", ");
        } 
    }
    public static void main(String args[]){ 
        // 開始時刻を取得
        long begin = System.nanoTime();
        // 計測対象の処理を実行
        new Example().test();
        // 終了時刻を取得
        long end = System.nanoTime();

        long time = end-begin;
        System.out.println();
        System.out.println("Elapsed Time: "+time);
    }
}

出力結果

0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231, 253, 276, 300, 325, 351, 378, 406, 435, 465, 496, 528, 561, 595, 630, 666, 703, 741, 780, 820, 861, 903, 946, 990, 1035, 1081, 1128, 1176, 1225, 1275,
Elapsed Time: 1530200

出力値はナノ秒単位のため、桁数が大きくなります。必要に応じて1,000,000で割ることでミリ秒へ変換できます。

例3:Instantクラスを使う方法

Java 8以降で導入された日時API(Date-Time API)を利用する方法です。コードの可読性が高く、現代的な書き方として推奨されています。

import java.time.Duration;
import java.time.Instant;
public class Example {
    public void test(){
        int num = 0;
        for(int i=0; i<=50; i++){ 
            num = num+i;
            System.out.print(num+", ");
        } 
    }
    public static void main(String args[]) { 
        // 開始時刻を取得
        Instant start = Instant.now();
        new Example().test();
        // 終了時刻を取得
        Instant end = Instant.now();
        long time = Duration.between(start, end).toMillis();
        System.out.println();
        System.out.println(time+" Milli seconds");
    }
}

出力結果

0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231, 253, 276, 300, 325, 351, 378, 406, 435, 465, 496, 528, 561, 595, 630, 666, 703, 741, 780, 820, 861, 903, 946, 990, 1035, 1081, 1128, 1176, 1225, 1275,
3 Milli seconds

例4:Apache CommonsのStopWatchクラスを使う方法

Apache Commons Langライブラリが提供するStopWatchクラスを使うと、開始・停止・計測結果の取得を明示的に行えるため、処理の意図がわかりやすいコードになります。

import org.apache.commons.lang3.time.StopWatch;
public class Example {
    public void test(){
        int num = 0;
        for(int i=0; i<=50; i++){ 
            num = num+i;
            System.out.print(num+", ");
        } 
    }
    public static void main(String args[]) { 
        // StopWatchクラスのインスタンスを生成
        StopWatch obj = new StopWatch();
        // ストップウォッチを開始
        obj.start();
        new Example().test();
        // ストップウォッチを停止
        obj.stop();
        System.out.println();
        System.out.println("Elapsed Time: "+obj.getTime() +" milli seconds");
    }
}

出力結果

0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231, 253, 276, 300, 325, 351, 378, 406, 435, 465, 496, 528, 561, 595, 630, 666, 703, 741, 780, 820, 861, 903, 946, 990, 1035, 1081, 1128, 1176, 1225, 1275,
Elapsed Time: 1 milli seconds

なお、StopWatchを使用するには、MavenやGradleでApache Commons Langへの依存関係を追加する必要があります。

例5:DateクラスのgetTime()メソッドを使う方法

import java.util.Date;
public class Demo{
    public void test(){
        int num = 0;
        for(int i=0; i<=50; i++){ 
            num = num+i;
            System.out.print(num+", ");
        } 
    }
    public static void main(String[] args) {
        long startTime = new Date().getTime();
        new Demo().test();
        long endTime = new Date().getTime();
        long time = endTime - startTime;
        System.out.println("Execution time: " + time);
    }
}

出力結果

0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231, 253, 276, 300, 325, 351, 378, 406, 435, 465, 496, 528, 561, 595, 630, 666, 703, 741, 780, 820, 861, 903, 946, 990, 1035, 1081, 1128, 1176, 1225, 1275,
Execution time: 5

例6:Calendarクラスを使う方法

import java.util.Calendar;
public class Demo{
    public void test(){
        int num = 0;
        for(int i=0; i<=50; i++){ 
            num = num+i;
            System.out.print(num+", ");
        } 
    }
    public static void main(String[] args) throws InterruptedException {
        long startTime = Calendar.getInstance().getTime().getTime();
        new Demo().test();
        long endTime = Calendar.getInstance().getTime().getTime();
        long time = endTime - startTime;
        System.out.println("Execution time: " + time);
    }
}

出力結果

0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231, 253, 276, 300, 325, 351, 378, 406, 435, 465, 496, 528, 561, 595, 630, 666, 703, 741, 780, 820, 861, 903, 946, 990, 1035, 1081, 1128, 1176, 1225, 1275,
Execution time: 20

各計測手法の比較と使い分けのポイント

手法精度特徴
System.currentTimeMillis()ミリ秒最も手軽な標準的な方法。簡易的な計測に向く
System.nanoTime()ナノ秒高精度計測に最適。システム時計の変更の影響を受けにくい
Instant / Durationミリ秒〜ナノ秒Java 8以降のモダンな日時API。可読性が高い
StopWatchミリ秒外部ライブラリが必要だが、直感的で扱いやすい
Date#getTime()ミリ秒レガシーな方法。新規コードでは非推奨
Calendarミリ秒レガシーな方法。日付操作が主目的のクラス

使い分けの目安:単純な処理時間の確認にはcurrentTimeMillis()、微細なパフォーマンス計測にはnanoTime()、新しいプロジェクトではInstant+Durationの組み合わせがおすすめです。また、複数区間の計測を行いたい場合はStopWatchが便利です。

なお、DateやCalendarは古い日時APIであり、スレッドセーフではないなどの問題があるため、新規開発ではJava 8以降のjava.timeパッケージを利用するのがベストプラクティスとされています。

  1. JavaのSwingUtilities.invokeLater()メソッドの使い方を徹底解説

    invokeLater()メソッドとはinvokeLater()メソッドは、SwingUtilitiesクラスが提供するstaticメソッドの一つで、AWTイベントディスパッチスレッド(Event Dispatch Thread)上でタスクを非同期に実行するために使用されます。このメソッドはSwingUtilities.invokeAndWait()とよく似た動作をしますが、大きな違いは、処理のリクエストをイベントキューに登録した後、すぐに呼び出し元へ制御を返すという点です。つまり、invokeLater()は引数で渡されたRunnableオブジェクト内のコードブロックの実行完了を待ちません。

  2. Excelで時間差を計算する方法|####エラーとAM/PM表示を解決するコツ

    Microsoft Excelは、予算管理や税額計算など、幅広い用途に活用できる強力な表計算ソフトです。豊富な機能を活かせば、電卓代わりとしても使えます。さらに、Excelでは2つの時刻の差(時間差)を計算することも可能です。たとえば、従業員の勤務開始時刻と終了時刻から実際の勤務時間を算出したり、勤務時間の記録を一元管理して給与や賃金の計算に役立てたりできます。 「時間差の計算なら、終了時刻から開始時刻を引くだけだから簡単」と思うかもしれません。しかし、単純に引き算を実行すると、2つの問題に直面します。この記事では、その問題点と具体的な解決方法をわかりやすく解説します。 Excelで時間差を