Präzisionstakt

M

Mr. S

Gast
Hallo!

Ich brauche für ein Program ein präzises Timing, welches mit wechselnden Lasten klar kommen muss. Ich brauche einen Start der Lastrechnung alle 50 ms. Wenn die Rechnung mehr als 50 ms dauert muss das nächste Intervall kürzer werden, wenn die Rechnung schneller fertig ist soll die Restzeit gewartet werden. Im folgenden ist das erste Programm zu sehen:
Java:
public class Program {
	public static long INTERVALL = 50;
	
	public static void main(String[] args) {
		Program p = new Program();
		try {
			p.run(args);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void run(String[] args) throws Exception {
		long start = System.nanoTime();
		long timeNanos, timeMillis, diff;
		for (int i=0; i<25; i++) {
			/* + Last + */
			int rand = (int)((Math.random()) * 60 + 10);
			Thread.sleep(rand);
			/* - Last - */
			timeNanos = System.nanoTime();   
			timeMillis = (timeNanos - start) / (1000 * 1000);
			diff = (i + 1) * INTERVALL - timeMillis;
			if (diff > 0) Thread.sleep(diff);
			long temp = (i + 1) * INTERVALL - (System.nanoTime() - start) / (1000 * 1000);
			System.out.println(i + "\t" + timeMillis + "\t" + diff + "\t" + rand + "\t" + temp);
		}  
	}
}
Mit einem Random-Sleep simuliere ich erst einmal die Last. Die Leistung ist allerdings nicht so prickelnd, recht ungenau das Ganze. Hat jemand Verbesserungsvorschläge?
 

Volvagia

Top Contributor
Versuche mal einen TimerTask. Die können mit scheduledAtFixedRate über langen Zeitraum genau ausgeführt werden. Also ich denke genau so wie du willst.
 
M

Mr. S

Gast
Nicht zu ungut, aber TimerTask war eine blöde Idee. Die Toleranz beträgt bis zu 150 ms, also dem dreifachen des eigentlichen Zeitsignals. Dann nehme ich lieber die 20 ms von System.nanoTime(), obwohl das schon fast die Hälfte des Intervalls ist. Kann sein das TimerTask bei größeren Zeitintervallen präzise arbeitet, aber für 50 ms ist das viel zu schlecht.

Java:
public class Program {
	public static long INTERVALL = 50;
	static Timer timer;
	static RemindTask timerTask;
	
	static class RemindTask extends TimerTask {
		public static long start = 0;
		public static long cnt = 1;
		
		public RemindTask() {
			start = System.nanoTime();
		}
		
		public void run() {
			// + Last +
			try {
				int rand = (int)((Math.random()) * 60 + 10);
				Thread.sleep(rand);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			// - Last -

			try {
				long timeNanos = System.nanoTime();   
				long timeMillis = (timeNanos - start) / (1000 * 1000);
				long diff = cnt * INTERVALL - timeMillis;
				if (diff > 0) Thread.sleep(diff);
				cnt++;
				long temp = cnt * INTERVALL - (System.nanoTime() - start) / (1000 * 1000);
				System.out.println(cnt + "\t" + timeMillis + "\t" + diff + "\t" + temp);
			} catch (Exception ex) {}
		}
	}

	public static void main(String[] args) {
		Program p = new Program();
		try {
			p.run(args);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void run(String[] args) throws Exception {
		timer = new Timer();
		timerTask = new RemindTask();
		timer.scheduleAtFixedRate(timerTask, 0, INTERVALL);
	}
}
 

faetzminator

Gesperrter Benutzer
Ich hab damals für einen Chip etwas in C programmiert, da hab ich die Taktung in Assembler geschrieben. Ob sich das allerdings mit JNI/JNA auf Java übertragen lässt und dabei kein Overhead (welcher deutlich langsamer als das "wait" ist) generiert wird, daran würde ich stark zweifeln.
 

Landei

Top Contributor
Ich habs zwar noch nicht selbst verwender, aber vielleicht hilft das Java Media Framework weiter, da gibt es ein Interface [c]Clock[/c], das z.B. von [c]Controller[/c] verwendet wird. Bei Audio und Video muss das Timing ja sehr genau sein...
 

Oben