Javaプログラミング学習サイト ゆるゆるプログラミング

2019/04/05 公開

・ストップウォッチ その2

ナノ秒単位で時間を測定できるストップウォッチのクラスを作成しました。

ここで紹介しているものは、開始/終了/一時停止/再開メソッドを呼び出して時間計測するクラスです。

以下が、ストップウォッチクラスと、そのクラスを呼び出すJavaソースコードの例です。

StopWatch2.java ← クリックしてダウンロードページに移動
001:    // ストップウォッチクラスを作成
002:    class MyStopWatch2 {
003:    	// 開始時間に初期値-1を代入
004:    	private long ts = -1;
005:    
006:    	// 終了時間に初期値-1を代入
007:    	private long te = -1;
008:    
009:    	// 計測時間に初期値0を代入
010:    	private long tresult = 0;
011:    
012:    	// 一時停止するまでの時間に初期値-1を代入
013:    	private long tresult_temp = -1;
014:    
015:    
016:    	// 開始メソッド
017:    	public void start()
018:    	{
019:    		// 計測時間に初期値0を代入
020:    		tresult = 0;
021:    
022:    		// 一時停止までの時間に初期値-1を代入
023:    		tresult_temp = -1;
024:    
025:    		// 開始時間を代入
026:    		ts = System.nanoTime();
027:    	}
028:    	
029:    	// 停止メソッド
030:    	public void stop()
031:    	{
032:    		// start()が呼ばれているか?
033:    		if ( 0 > ts ) return;
034:    
035:    		// 終了時間を代入
036:    		te = System.nanoTime();
037:    
038:    		// 計測時間を代入
039:    		if ( 0 <= tresult_temp )
040:    			// 一時停止あり
041:    			tresult = te - ts + tresult_temp;
042:    		else
043:    			// 一時停止なし
044:    			tresult = te - ts;
045:    	}
046:    
047:    	// クリアメソッド
048:    	public void clear()
049:    	{
050:    		// 開始終了時間に初期値-1を代入
051:    		ts = -1;
052:    		te = -1;
053:    
054:    		// 計測時間に初期値0を代入
055:    		tresult = 0;
056:    
057:    		// 一時停止までの時間に初期値-1を代入
058:    		tresult_temp = -1;
059:    	}
060:    
061:    	// 一時停止メソッド
062:    	public void suspend()
063:    	{
064:    		// start()が呼ばれているか?
065:    		if ( 0 > ts ) return;
066:    
067:    		// 終了時間を代入
068:    		te = System.nanoTime();
069:    
070:    		// 一時停止するまでの時間を計算
071:    		tresult_temp += te - ts;
072:    
073:    		// 計測時間に一時停止するまでの時間を代入
074:    		tresult = tresult_temp;		
075:    
076:    		// 開始終了時間に初期値-1を代入
077:    		ts = -1;
078:    		te = -1;
079:    	}
080:    
081:    	// 再開メソッド
082:    	public void resume()
083:    	{
084:    		// 一時停止中か?
085:    		if ( ( 0 <= tresult_temp ) && ( 0 > ts ) ) {
086:    			// 一時停止中
087:    			// 開始時間を代入
088:    			ts = System.nanoTime();
089:    		}
090:    	}
091:    
092:    	// 計測時間をナノ秒で返す
093:    	public long nanotime()
094:    	{
095:    		return tresult;
096:    	}
097:    }
098:    
099:    
100:    // メイン
101:    public class StopWatch2 {
102:    	public static void main( String[] args ) {
103:    		// ストップウォッチクラスを作成
104:    		MyStopWatch2 sw = new MyStopWatch2();
105:    
106:    		try {
107:    			// スタート
108:    			sw.start();
109:    
110:    			// 500ミリ秒停止
111:    			Thread.sleep( 500 );
112:    
113:    			// 一時停止
114:    			sw.suspend();
115:    
116:    			// 300ミリ秒停止
117:    			Thread.sleep( 300 );
118:    
119:    			// 再開
120:    			sw.resume();
121:    
122:    			// 200ミリ秒停止
123:    			Thread.sleep( 200 );
124:    
125:    			// 一時停止
126:    			sw.suspend();
127:    
128:    			// 100ミリ秒停止
129:    			Thread.sleep( 100 );
130:    
131:    			// 再開
132:    			sw.resume();
133:    
134:    			// 200ミリ秒停止
135:    			Thread.sleep( 200 );
136:    
137:    			// ストップ
138:    			sw.stop();
139:    
140:    			// 時間計測結果を表示
141:    			// 計測時間をナノ秒で取得
142:    			long tnsec = sw.nanotime();
143:    
144:    			// 処理時間 ミリ秒
145:    			double tmsec = (double)tnsec / 1000000.0;
146:    
147:    			// 処理時間 秒
148:    			double tsec = tmsec / 1000.0;
149:    
150:    			System.out.println( "時間 : " + tnsec + "ナノ秒   "
151:    					+ tmsec + "ミリ秒   " + tsec + "秒" );
152:    		}
153:    		catch( InterruptedException e )
154:        		{
155:    			return;
156:        		}
157:    
158:    	}
159:    }

StopWatch2.javaの出力結果

時間 : 900112001ナノ秒   900.112001ミリ秒   0.900112001秒

この結果から、プログラム中に複数あるThread.sleepうち、suspendメソッドとresumeメソッドの間の時間が出力結果に反映されていないことが確認できます。

それでは、ここからストップウォッチのソースコードを解説していきます。

001:    // ストップウォッチクラスを作成
002:    class MyStopWatch2 {

クラス名を、StopWatch2としています。

003:    	// 開始時間に初期値-1を代入
004:    	private long ts = -1;
005:    
006:    	// 終了時間に初期値-1を代入
007:    	private long te = -1;
008:    
009:    	// 計測時間に初期値0を代入
010:    	private long tresult = 0;
011:    
012:    	// 一時停止するまでの時間に初期値-1を代入
013:    	private long tresult_temp = -1;

メンバ変数を宣言しています。tsとteは、それぞれ時間計測の開始時間と終了時間を代入するlong型変数で、初期値はどちらも-1です。tresultは、計測結果を代入するlong型変数で、初期値は0です。tresult_tempは、一時停止した時間までの計測結果を代入するlong型変数で、初期値は-1です。

016:    	// 開始メソッド
017:    	public void start()
018:    	{
019:    		// 計測時間に初期値0を代入
020:    		tresult = 0;
021:    
022:    		// 一時停止までの時間に初期値-1を代入
023:    		tresult_temp = -1;
024:    
025:    		// 開始時間を代入
026:    		ts = System.nanoTime();
027:    	}

start()は、開始メソッドでStartボタンを意味します。計測時間tresultに0、一時停止までの時間result_tempに-1、開始時間tsにシステムタイマーの値を代入しています。System.nanoTime()でナノ秒単位のシステムタイマーを取得することができます。

System.nanoTimeメソッド

public static long nanoTime()
■システムタイマーの値をナノ秒単位で返します。

  パラメータ なし

  戻り値     システムタイマーの現在の値をナノ秒単位で返します。

開始時間ts=-1は、時間計測が開始していない状態で、一時停止までの時間result_temp=-1は、一時停止(suspend)が一度も呼ばれていない状態です。

030:    	public void stop()
031:    	{
032:    		// start()が呼ばれているか?
033:    		if ( 0 > ts ) return;
034:    
035:    		// 終了時間を代入
036:    		te = System.nanoTime();
037:    
038:    		// 計測時間を代入
039:    		if ( 0 <= tresult_temp )
040:    			// 一時停止あり
041:    			tresult = te - ts + tresult_temp;
042:    		else
043:    			// 一時停止なし
044:    			tresult = te - ts;
045:    	}

stop()は、終了メソッドでStopボタンを意味します。開始時間tsが0未満であればstart()メソッドが呼ばれていないのでメソッドreturn文で抜けます。結果として計測時間tresultは0となります。開始時間tsが0以上の場合、終了時間teにシステムタイマーの値を代入しします。次に計測時間tresultに値を代入します。その値は、一時停止した時間が有る場合( 0 <= tresult_temp )には、計測時間tresultに( te - ts ) + tresult_tempを代入します。無い場合には、計測時間tresultに( te - ts )を代入します。

047:    	// クリアメソッド
048:    	public void clear()
049:    	{
050:    		// 開始終了時間に初期値-1を代入
051:    		ts = -1;
052:    		te = -1;
053:    
054:    		// 計測時間に初期値0を代入
055:    		tresult = 0;
056:    
057:    		// 一時停止までの時間に初期値-1を代入
058:    		tresult_temp = -1;
059:    	}

clear()は、クリアメソッドでResetボタンを意味します。開始時間tsと終了時間teに-1、計測結果tresultに0、一時停止までの時間tresult_tempに0を代入しています。

061:    	// 一時停止メソッド
062:    	public void suspend()
063:    	{
064:    		// start()が呼ばれているか?
065:    		if ( 0 > ts ) return;
066:    
067:    		// 終了時間を代入
068:    		te = System.nanoTime();
069:    
070:    		// 一時停止するまでの時間を計算
071:    		tresult_temp += te - ts;
072:    
073:    		// 計測時間に一時停止するまでの時間を代入
074:    		tresult = tresult_temp;		
075:    
076:    		// 開始終了時間に初期値-1を代入
077:    		ts = -1;
078:    		te = -1;
079:    	}

suspend()は、一時停止メソッドです。開始時間tsが0未満であればstart()メソッドが呼ばれていないのでメソッドreturn文で抜けます。開始時間tsが0以上の場合、終了時間teにシステムタイマーの値を代入しします。次に、一時停止するまでの時間tresult_tempに( te - ts )を足し、計測結果tresultにtresult_tempを値を代入します。その後、開始時間tsと終了時間tsに-1を代入しています。

081:    	// 再開メソッド
082:    	public void resume()
083:    	{
084:    		// 一時停止中か?
085:    		if ( ( 0 <= tresult_temp ) && ( 0 > ts ) ) {
086:    			// 一時停止中
087:    			// 開始時間を代入
088:    			ts = System.nanoTime();
089:    		}
090:    	}

resume()は、再開メソッドです。一時停止するまでの時間tresult_tempが0以上で、開始時間tsが0未満であれば一時停止中なので、開始時間tsにシステムタイマーの値を代入しています。これで計測が再開された状態になります。

092:    	// 計測時間をナノ秒で返す
093:    	public long nanotime()
094:    	{
095:    		return tresult;
096:    	}

nanotime()は、計測時間をナノ秒で返すメソッドです。計測結果tresultをlong型で返します。

100:    // メイン
101:    public class StopWatch2 {
102:    	public static void main( String[] args ) {
103:    		// ストップウォッチクラスを作成
104:    		MyStopWatch2 sw = new MyStopWatch2();
105:    
106:    		try {
107:    			// スタート
108:    			sw.start();
109:    
110:    			// 500ミリ秒停止
111:    			Thread.sleep( 500 );
112:    
113:    			// 一時停止
114:    			sw.suspend();
115:    
116:    			// 300ミリ秒停止
117:    			Thread.sleep( 300 );
118:    
119:    			// 再開
120:    			sw.resume();
121:    
122:    			// 200ミリ秒停止
123:    			Thread.sleep( 200 );
124:    
125:    			// 一時停止
126:    			sw.suspend();
127:    
128:    			// 100ミリ秒停止
129:    			Thread.sleep( 100 );
130:    
131:    			// 再開
132:    			sw.resume();
133:    
134:    			// 200ミリ秒停止
135:    			Thread.sleep( 200 );
136:    
137:    			// ストップ
138:    			sw.stop();
139:    
140:    			// 時間計測結果を表示
141:    			// 計測時間をナノ秒で取得
142:    			long tnsec = sw.nanotime();
143:    
144:    			// 処理時間 ミリ秒
145:    			double tmsec = (double)tnsec / 1000000.0;
146:    
147:    			// 処理時間 秒
148:    			double tsec = tmsec / 1000.0;
149:    
150:    			System.out.println( "時間 : " + tnsec + "ナノ秒   "
151:    					+ tmsec + "ミリ秒   " + tsec + "秒" );
152:    		}
153:    		catch( InterruptedException e )
154:        		{
155:    			return;
156:        		}
157:    
158:    	}
159:    }

startメソッドとstopメソッドの間で、Thread.sleepを複数回実行しています。ここで、一時停止(suspendメソッド)と再開(resumeメソッド)で囲まれたThread.sleepの値は、最終的な計測結果に反映されていないことを確認してみてください。

Thread.sleepはtry { ~ } catchの間に書く必要があるので、このサンプルソースでは106行~152行の間をtry { ~ }で大きく囲んでいます。

■単純なストップウォッチ

ストップウォッチ その1 単純なストップウォッチクラスの作り方を解説

■関連コンテンツ

時間計測 時間を計測する方法を解説

■新着情報

2022.07.07 外部プログラムの実行 exeファイル実行
2022.07.06 完全数 6=1+2+3

■広告

 

 

 

 

 

スッキリわかるJava入門第3版 [ 中山清喬 ]

価格:2,860円
(2021/6/18 14:32時点)
感想(6件)

 

 

 

 

Topへ