9

事前定義された時間コードを実行する必要があります。時間が経過したら、コードを停止する必要があります。現在、TimerTaskを使用してコードを一定時間実行できるようにしていますが、これにより、コードによって無限のスレッドが作成され、単に効率的ではありません。より良い代替案はありますか?

現在のコード;

// Calculate the new lines to draw 
            Timer timer3 = new Timer();
            timer3.schedule(new TimerTask(){
                public void run(){
                    ArrayList<String> Coords = new ArrayList<String>();
                    int x = Float.valueOf(lastFour[0]).intValue();
                    int y = Float.valueOf(lastFour[1]).intValue();
                    int x1 = Float.valueOf(lastFour[2]).intValue();
                    int y1 = Float.valueOf(lastFour[3]).intValue();
                    //Could be the wrong way round (x1,y1,x,y)?
                    Coords = CoordFiller.coordFillCalc(x, y, x1, y1);
                    String newCoOrds = "";
                    for (int j = 0; j < Coords.size(); j++)
                    {
                        newCoOrds += Coords.get(j) + " ";
                    }
                    newCoOrds.trim();
                    ClientStorage.storeAmmendedMotion(newCoOrds);

                }

            }
            ,time);
4

4 に答える 4

17

Java5以降を使用している場合は、とを検討ScheduledThreadPoolExecutorしてFutureください。Timer前者を使用すると、指定された遅延の後、または指定された間隔で実行されるタスクをスケジュールできるため、より確実にの役割を引き継ぐことができます。

このTimer機能は、延期(「このタスクを100ミリ秒で実行」)および定期的(「このタスクを10ミリ秒ごとに実行」)タスクの実行を管理します。ただし、Timerいくつかの欠点がありScheduledThreadPoolExecutor、その代替として考える必要があります。[...]

ATimerは、タイマータスクを実行するための単一のスレッドのみを作成します。タイマータスクの実行に時間がかかりすぎると、他TimerTaskのタスクのタイミング精度が低下する可能性があります。繰り返しTimerTaskが10ミリ秒ごとに実行されるようにスケジュールされ、別TimerTaskのタスクの実行に40ミリ秒かかる場合、繰り返しタスクは、長時間実行タスクが完了した後、(固定レートまたは固定遅延のどちらでスケジュールされたかに応じて)4回連続して呼び出されます。 、または4つの呼び出しを完全に「見逃します」。スケジュールされたスレッドプールは、延期された定期的なタスクを実行するための複数のスレッドを提供できるようにすることで、この制限に対処します。

のもう1つの問題は、がチェックされていない例外をスローするTimerと、動作が低下することです。TimerTaskスレッドはTimer例外をキャッチしないため、TimerTask終了からスローされたチェックされていない例外はタイマースレッドを終了します。Timerまた、この状況ではスレッドを復活させません。代わりに、全体Timerがキャンセルされたと誤って想定します。この場合、TimerTaskすでにスケジュールされているがまだ実行されていないは実行されず、新しいタスクをスケジュールすることはできません。

Java Concurrency in Practice、セクション6.2.5から。

また、Futuresは、最大で指定された時間実行するように制約できますTimeoutException(時間内に終了できなかった場合はaをスローします)。

アップデート

上記が気に入らない場合は、以下のように、タスクに独自の実行時間を測定させることができます。

int totalTime = 50000; // in nanoseconds
long startTime = System.getNanoTime();
boolean toFinish = false;

while (!toFinish) 
{
    System.out.println("Task!");
    ...
    toFinish = (System.getNanoTime() - startTime >= totalTime);
}
于 2011-02-09T22:02:34.300 に答える
4

[...]現在、TimerTaskを使用して、コードを設定された時間実行できるようにしています[...]

タイマータスクは、現在実行中のタスクを停止することはありません。実際、タスクを何度もやり直すことが唯一の目的です。

実行タスクとの緊密な協力なしにこれを解決する簡単な方法はありません。最善の方法は、タスクが自身の実行を監視し、時間切れになったときにタスクが戻る(終了する)ことを確認することです。

于 2011-02-09T21:57:54.393 に答える
0

停止することでプログラムを終了する必要がある場合、解決策は、処理用のスレッドを作成してデーモンとしてマークし、それを開始してメインスレッドで必要な時間スリープし、main()メソッドから戻ることです。

停止することで、処理を停止することを意味する場合は、それをスクラッチします。

于 2011-02-09T22:01:49.733 に答える
0

通常、作成する必要があるのは1つのTimer()のみであることに注意してください。コードスニペットから、複数のTimer()オブジェクトを作成していると思います。

scheduleメソッドの時間は、実行する時間であり、実行する時間ではありません。

制限時間を超えた場合は、forループの前に開始時間を設定し、forループにブレークを設定することを検討してください。

long startedAt = System.currentTimeMillis();
long finishedCorrectly = true;
for (int j = 0; j < Coords.size(); j++) {
  newCoOrds += Coords.get(j) + " ";
  if ((System.currentTimeMillis() - startedAt) > MAX_TIME_TO_RUN) {
    finishedCorrectly = false;
    break;
  }
}
于 2011-02-09T22:21:12.520 に答える