2015-04-26 6 views
2

Я выполняю некоторые задачи с использованием 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 мс?

Благодаря

+0

Способ измерения времени, в течение которого метод 'run' exectuted for is wrong. Вам нужно рассчитать его как «текущее время после выполнения операции печати» - текущее время перед запуском печати. – CKing

+0

Я не думаю, что это то, что он хочет. Он просто хочет записать время, в которое был запущен метод. –

+0

Вы должны взять значения, полученные из 'nanoTime()', с помощью [зерна соли] (http://shipilev.net/blog/2014/nanotrusting-nanotime /). –

ответ

4

Я не думаю, что вы собираетесь быть в состоянии справиться с этим в Java с этим уровнем точности. В отличие от ваших решений C/Win32, ваше Java-решение работает в JVM с несколькими потоками (с различным приоритетом) и с запуском мусора и использованием ресурсов.

Сказав это, я бы экспериментировал с методом scheduleAtFixedRate(), который выполняется в регулярный период.scheduleWithFixedDelay() будет выполнять и после завершения задержки на фиксированный период времени. Следовательно, не учитывается время, затраченное на фактический запуск вашего метода.

+0

Не забывайте, что время печатается до завершения метода 'run' или после ввода метода' run', поэтому OP должен учитывать время, потерянное между print и ввод/возврат из метода run? – CKing

+0

@bot, да, вы правы, я также установил 1 или 2 секунды вместо миллисекунд, чтобы попробовать. Результат по-прежнему не точным. –

Смежные вопросы