Я выполняю некоторые задачи с использованием Java. У меня есть некоторые проблемы с синхронизацией: мне нужно настроить таймер с фиксированным периодом повторения. Я пробовал оба стандартные Timer
и TimerTask
и ScheduledExecutor
, но и работу в приблизительной форме, то есть, если я установить интервал в 40 миллисекунд, используя следующий код (для Executors
)Действительный фиксированный временной интервал Java
m_executor = Executors.newScheduledThreadPool(5);
Runnable thread = new TheThread();
m_executor.scheduleWithFixedDelay(thread, 0, 40000000, TimeUnit.NANOSECONDS);
И тогда я стараюсь печатать "время" каждого исполнения
private static final class TheThread implements Runnable {
@Override
public void run() {
System.out.println(System.nanoTime()/1000000);
}
}
в результате получается нечто вроде этого:
xxxxxx300
xxxxxx345
xxxxxx386
xxxxxx428
...
Как вы можете видеть, если я правильно понимаю nanoTime()
, функция вызывается в случайных интервалах, близких к указанным мной (40 миллисекунд), но не точно, что я указал!
Когда я работал с C и Win32s, например, я был в состоянии использовать функцию CreateTimerQueueTimer()
, которая с высокой точностью, а функция обратного вызова называлась каждые 40 миллисекунд:
xxxxxx300
xxxxxx340
xxxxxx380
...
Может кто-нибудь из вас дать мне несколько намеков?
Благодаря
EDIT
Я пытался переместить измерение времени, чтобы избежать время печати. Я также пытался использовать scheduleAtFixedRate()
, но, к сожалению, период варьируется от 35 до 47 мс (в методе 40).
Я бродил, как люди могут сделать программное обеспечение таких эмуляторов или подобные вещи, что требует точного период соблюдения ... :-)
EDIT 2
OK ребят ... могу я меняя дорогу, но я подумал о возможном решении, которое я хотел бы показать вам, и спросить вас, экспертов :), как эта идея может быть применима (и безопасна)
Проблема заключается в том, чтобы запускать некоторые методы каждый X миллисекунд, скажем, 40 мс. Здесь речь идет о таймере/времени Java, но как насчет этого простого решения?
public class MyEmulator extends Thread {
private long start = 0;
private long end = 0;
@Override
public void run() {
long exec_time;
start = System.nanoTime();
/*
* Do the emulator-loop
*/
end = System.nanoTime();
exe_time = (end - start)/1000000;
// wait with a whil() (40 - exec_time)
}
}
С помощью этого решения, когда я печатаю истекшее время после того, как ожидание whilt()
закончился результат ровно 40 мс (без десятичного знака, что не бросить важно).
Считаете ли вы, что это безопасно, то есть действительно 40 мс?
Благодаря
Способ измерения времени, в течение которого метод 'run' exectuted for is wrong. Вам нужно рассчитать его как «текущее время после выполнения операции печати» - текущее время перед запуском печати. – CKing
Я не думаю, что это то, что он хочет. Он просто хочет записать время, в которое был запущен метод. –
Вы должны взять значения, полученные из 'nanoTime()', с помощью [зерна соли] (http://shipilev.net/blog/2014/nanotrusting-nanotime /). –