可変遅延があるScheduleDexeCutorService
-
19-09-2019 - |
質問
java.util.concurrent.blockingqueueから要素を引き出して処理しているタスクがあるとします。
public void scheduleTask(int delay, TimeUnit timeUnit)
{
scheduledExecutorService.scheduleWithFixedDelay(new Task(queue), 0, delay, timeUnit);
}
周波数を動的に変更できる場合、タスクをスケジュール /再スケジュールするにはどうすればよいですか?
- アイデアは、データの更新のストリームを取得し、それらをバッチでGUIに伝播することです
- ユーザーは更新の頻度を変えることができるはずです
解決
固定レート遅延を変更できるとは思いません。使用する必要があると思います スケジュール() ワンショットを実行し、1回完了したら再度スケジュールします(必要に応じて変更されたタイムアウトを変更します)。
他のヒント
使用する schedule(Callable<V>, long, TimeUnit)
それよりも scheduleAtFixedRate
また scheduleWithFixedDelay
. 。次に、あなたの呼び出しが可能であることを確認します 再スケジュール自体または新しい呼び出し可能なインスタンス 将来のある時点で。例えば:
// Create Callable instance to schedule.
Callable<Void> c = new Callable<Void>() {
public Void call() {
try {
// Do work.
} finally {
// Reschedule in new Callable, typically with a delay based on the result
// of this Callable. In this example the Callable is stateless so we
// simply reschedule passing a reference to this.
service.schedule(this, 5000L, TimeUnit.MILLISECONDS);
}
return null;
}
}
service.schedule(c);
このアプローチは、シャットダウンして再作成する必要性を回避します ScheduledExecutorService
.
使用してはいけません scheduleAtFixedRate
特定の間隔でいくつかのキュータスクを処理しようとしている場合は? scheduleWithFixedDelay
指定された遅延が待機してから、キューから1つのタスクを実行します。
どちらの場合でも、 schedule*
aの方法 ScheduledExecutorService
返品します ScheduledFuture
参照。レートを変更したい場合は、 ScheduledFuture
異なるレートでタスクを再スケジュールします。
schedulewithfixeddelay(...)runnableScheduledfutureを返します。それを再スケジュールするために、あなたはそれをキャンセルして再スケジュールするだけです。それを再スケジュールするために、あなたは単にrunnableScheduledfutureを新しい実行可能にするために包むことができます:
new Runnable() {
public void run() {
((RunnableScheduledFuture)future).run();
}
};
私は最近、ScheduledFutureを使用してこれをしなければなりませんでしたが、Runnableなどをラップしたくありませんでした。これが私がそれをした方法です:
private ScheduledExecutorService scheduleExecutor;
private ScheduledFuture<?> scheduleManager;
private Runnable timeTask;
public void changeScheduleTime(int timeSeconds){
//change to hourly update
if (scheduleManager!= null)
{
scheduleManager.cancel(true);
}
scheduleManager = scheduleExecutor.scheduleAtFixedRate(timeTask, timeSeconds, timeSeconds, TimeUnit.SECONDS);
}
public void someInitMethod() {
scheduleExecutor = Executors.newScheduledThreadPool(1);
timeTask = new Runnable() {
public void run() {
//task code here
//then check if we need to update task time
if(checkBoxHour.isChecked()){
changeScheduleTime(3600);
}
}
};
//instantiate with default time
scheduleManager = scheduleExecutor.scheduleAtFixedRate(timeTask, 60, 60, TimeUnit.SECONDS);
}