Ответ 1
Попробуйте ScheduledThreadPoolExecutor. Это должно дать более надежные результаты синхронизации.
У меня есть требование приостановить цикл while для определенного количества миллисекунд. Я попытался использовать Thread.sleep(продолжительность), но это не точно, особенно в сценарии цикла. Миллисекундная точность важна в моей программе.
Вот алгоритм, в котором я не хочу возвращаться, чтобы проверить условие до тех пор, пока expectedElapsedTime
не пройдет.
while (condition) {
time = System.currentTimeMillis();
//do something
if (elapsedTime(time) < expectedElapsedTime) ) {
pause the loop // NEED SUBSTITUTE FOR Thread.sleep()
}
// Alternative that I have tried but not giving good results is
while ((elapsedTime(time) < expectedElapsedTime)) {
//do nothing
}
}
long elapsedTime(long time) {
long diff = System.currentTimeMillis() - time;
return diff;
}
Попробуйте ScheduledThreadPoolExecutor. Это должно дать более надежные результаты синхронизации.
Чего вы ожидаете?
Если вы пойдете спать, то, как только ваш процесс снова будет работать, ему придется подождать, пока планировщик потоков заплатит его снова.
Я имею в виду, если вы идете спать в течение 50 секунд, это не значит, что ваш процесс будет работать ровно через 50 секунд. Поскольку он просыпается и запускается, ему придется ждать, чтобы запланировать процессор, который занимает дополнительное время плюс время, которое у вас есть для переключения контекста.
Нет ничего, что можно было бы сделать, чтобы контролировать его, чтобы вы не могли точно сказать то, что вы говорите.
В вашем случае я бы предложил круговую петлю.
long now = System.currentTimeMillis();
while(now < expectedElapsedTime){
now = System.currentTimeMillis();
}
Java не является системой реального времени, вы не можете заставить поток уйти и вернуться к такому жесткому графику. Чтобы запланировать выполнение вашей программы до миллисекунды, вам нужно использовать другую платформу - например, простое расширение RRJ или Java Real-Time.
Задержка, вероятно, будет произвольно выбрана, поэтому я бы поставил под сомнение вашу потребность в сроках временного интервала.
Если вам нужно время чтения, вам нужно заняться, ожидая достигнутого времени. Отказ от CPU означает, что вы не можете гарантировать, что получите его обратно, когда захотите.
Вы можете реализовать механизм wait/notify и делегировать другому потоку ответственность за уведомление другого потока в состоянии ожидания о том, что количество времени прошло и что оно может идти вперед...
Например, когда threadA нужно подождать некоторое время, вы можете поместить состояние ожидания в очередь и запустить задачу таймера, которая после определенного количества времени (интервала) вызывает уведомление и пробуждает ThreadA, которые идут вперед, это может быть альтернативой.
Если вы хотите быть точным со звуками, вы используете секвенсор и задаете темп в BPM: sequencer.setTempoInBPM(120);
Решение заключается в использовании обработчика с runnable и использования метода postDelayed. Пример:
new Handler().postDelayed(new Runnable() {
public void run () {
// Do delayed stuff!
}
}, 5000L); //5 seconds delay
Не забывайте о паузах сборщика мусора. Он может превзойти все ваши планы.