3

nいくつかのアクションを実行するオブジェクトがあります。アクションを実行すると、タイムスタンプが更新されます。ここで、タイムスタンプがたとえば 60 秒よりも古いかどうかを検証するタイムアウト スレッドを実装したいと考えています。

私の最初の解決策は、最後のタイムスタンプを含むすべてのオブジェクトのリストを保持しているスレッド (while-loop + sleep) でそれを行うことでした。ここで、スレッドがタイムアウトを決定するために 59 秒とスリープ時間を必要とする最悪のシナリオがあるという問題があります。

遅延時間を更新できるタイマーのようなソリューションを探しています。

何か案は?

4

3 に答える 3

2

wait/notify で監視オブジェクトを使用することは合理的だと思います (JDK >= 5 を使用している場合は、await/signal で Condition を使用できます)。

アイデアは簡単です:

ワーカー スレッド:

doYourActualWork();
synchronized(jobFinishedMonitor) {
    updateTimestamp();

    jobFinishedMonitor.notify();
}

タイムアウト スレッド:

synchronized(jobFinishedMonitor) {
    while(within60Second(timestamp)) {
        jobFinishedMonitor.wait(60);
    }
    if (within60Second(timestamp)) {
        timeoutHappened=true;
    }
 }
 if (timeoutHappened) {
     // do timeout handling
 }
于 2012-07-25T03:23:30.677 に答える
1

質問については、タイムアウトで何をしたいのか明確ではありません。ここでは、軽量タイムアウトを実装するための 2 つのオプションを紹介します。監視と制御です。

監視タイムアウト

グローバル タイマーの場合Timer、JDK の機能を使用できます。

public TimeoutTask implements TimerTask {
    List<MonitorableObject>  objects;
    public TimeoutTask(List<MonitorableObject> objects) {
        // make sure you can share this collection concurrently, 
        // e.g. copyonwritearraylist
        this.objects = objects;
    }
    public void run() {
       // objects -> filter(isTimeOut(currentTime)) -> do something
    }
}

Timer timer = new Timer();
timer.schedule(new TimeoutTask(myObjectList), 0,60*1000); // repeat each 60secs

を使用して同様の構成が可能ScheduledExecutorServiceです:

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
// Note that I can use here TimeoutTask b/c TimerTask is a Runnable - 
// this is just for the example. You'd better implement a plain runnable.
scheduler.schedule(new TimeoutTask(myObjectList), 60, TimeUnit.SECONDS); 

スレッドのプールを保持できるため、私はScheduledExecutorService上記のTimer機能を好みます。SchedulerExecutorまた、基になるスレッドプールはscheduledExecutorService.execute(...)、即時の同時実行 (スケジュールされていない) を呼び出す他の操作に使用できるため、専用のタイマー関数ではなく、汎用のエグゼキューター機能になります。

どちらの場合も、監視しているオブジェクトからタイムアウト値を安全に取得するために特別な注意を払う必要があります。通常、オブジェクトの同期メソッドを使用して、オブジェクトのタイムアウト ステータスを要求します。

強制タイムアウト

ExecutorService は、指定されたタイムアウト内で一連のタスクを実行するための API を提供します。例えば

List<Callable<?>> myTasks = ...;
// populate myTasks with Callable`s that wrap your intended execution

ExecutorService executorService = ... ;

List<Future<?>> results = executorService.invokeAll(myTasks, 60, TimeUnit.SECONDS);

このメソッドが戻った後、指定された時間内に成功したかどうかをすべての Future に問い合わせることができます。

于 2012-07-25T09:39:03.703 に答える
0

タイムスタンプを更新するたびにスレッドを中断します。次に、ループし、何もすることがなく、スリープし、タイムスタンプに何も起こらなかった場合は期限切れになります。もう一度中断された場合は、はるかに優れています。また、常に 60 マイナス (現在の時刻から最も古いタイムスタンプを引いた時間) を超えてスリープすることはありません。

于 2012-07-25T01:33:55.137 に答える