Javaでタイマーを設定する方法は?


151

タイマーを2分間設定してデータベースに接続しようとすると、接続に問題がある場合に例外をスローする方法を教えてください。


1
OPは、少なくとも2分間アクションを単純に試行することを望んでいるか、または接続の試行が現在進行中であっても、2分後に例外をスローする必要があるかどうかを
明確に

回答:


280

だから、答えの最初の部分は、これが私が最初にそれを解釈した方法であり、何人かの人々が役に立ったと思ったので、被験者が尋ねる事をどのように行うかです。その後、質問が明確になり、それに対処するために回答を拡張しました。

タイマーを設定する

まず、タイマーを作成する必要があります(java.utilここではバージョンを使用しています)。

import java.util.Timer;

..

Timer timer = new Timer();

一度タスクを実行するには:

timer.schedule(new TimerTask() {
  @Override
  public void run() {
    // Your database code here
  }
}, 2*60*1000);
// Since Java-8
timer.schedule(() -> /* your database code here */, 2*60*1000);

実行した後にタスクを繰り返すには:

timer.scheduleAtFixedRate(new TimerTask() {
  @Override
  public void run() {
    // Your database code here
  }
}, 2*60*1000, 2*60*1000);

// Since Java-8
timer.scheduleAtFixedRate(() -> /* your database code here */, 2*60*1000, 2*60*1000);

タスクをタイムアウトにする

明確にされた質問がすることを具体的に行うには、それは特定の期間タスクを実行しようとすることであり、次のようにすることができます。

ExecutorService service = Executors.newSingleThreadExecutor();

try {
    Runnable r = new Runnable() {
        @Override
        public void run() {
            // Database task
        }
    };

    Future<?> f = service.submit(r);

    f.get(2, TimeUnit.MINUTES);     // attempt the task for two minutes
}
catch (final InterruptedException e) {
    // The thread was interrupted during sleep, wait or join
}
catch (final TimeoutException e) {
    // Took too long!
}
catch (final ExecutionException e) {
    // An exception from within the Runnable task
}
finally {
    service.shutdown();
}

これは、タスクが2分以内に完了した場合を除いて、通常どおり実行されます。それより長く実行すると、TimeoutExceptionがスローされます。

1つの問題は、2分後にTimeoutExceptionが発生しますが、タスクは実際には実行され続けますが、おそらくデータベースまたはネットワーク接続が最終的にタイムアウトし、スレッドで例外がスローされることです。ただし、それが発生するまでリソースを消費する可能性があることに注意してください。


ああ、あなたは私の問題を間違っていると思います、私は毎回2分まで繰り返しデータベースに接続しようとする必要があります
Ankita

申し訳ありませんが、私の要件は、データベースへの接続に2分間与えて、それからいくつかのエラーメッセージがスローされることです。それは、データベースへの接続を試行する時間制限を設定するようなものです
Ankita

7
読者への注意:この答えは明らかに間違っています。2分間待機するようにタイマーを設定し、その2分の遅延後にDBクエリを実行し、2分ごとに繰り返し実行します。それがしていないことは、DBクエリをすぐに実行し、2分後に失敗することです。これは、質問で求められているとおりです(コメントで明確化されています)。
AgilePro 2013

2
@AgileProそれは本当だった。最終的に述べられた質問に答えなかったので、これに対処するために更新しました。
andrewmu 2013

1
@ErnestasGruodisコアAPIはコンストラクタをパブリックとしてリストします:docs.oracle.com/javase/7/docs/api/java/util/Timer.html#Timer()クラスパスに別のタイマークラスがある可能性があります-javaを試してください。クラスとしてのutil.Timer。
andrewmu 2013

25

これを使って

long startTime = System.currentTimeMillis();
long elapsedTime = 0L.

while (elapsedTime < 2*60*1000) {
    //perform db poll/check
    elapsedTime = (new Date()).getTime() - startTime;
}

//Throw your exception

1
うーん...これでしょう、技術的作業、それはあなたがOPで必要とされるDBの世論調査を、実行しているとして、あなたは時間がなくなるエッジケースをカバーしていない以外
thecoshman

1
これが唯一の正解です。単一のスレッドで実行され、ドリフトなしで終了時間を計算します。この場合、TimerTaskを使用するのはまったく間違っています。StackOverflowの多くの例がこの同じ種類の間違った頭のことを示唆していることに驚いています。
AgilePro 2013年

1
@thecoshman-タイマーの実装は、いったん進行中のDB操作を中断することも、中断することもありません。いずれの場合でも、制御できるのは、DB操作を開始する時間のみです。物事の時間を計るためには「タイマー」が必要であるという一般的な誤解がありますが、必要ではありません。あなたは何かをする必要があるだけであり、現在の時間を使用することによって、それをあまりにも長くしないようにしてください。
AgilePro 2013年

接続を返すか、正確に2分後にスローする必要があるとしましょう。これは機能しません。接続を試みてから2分経っても接続に失敗する場合は、このようになります。接続チェックに2週間ほどかかる場合、例外をスローするのにそれだけ時間がかかります。
thecoshman 2013年

14
これは実際には非常に悪いコーディングスタイルです。それは、whileループが常に実行され、何かをチェックするからです... CPUとバッテリー寿命に悪影響を及ぼします。
無限の

11

わかりました、私は今あなたの問題を理解していると思います。Futureを使用して何かを試み、何も起こらなかった場合は少し後にタイムアウトすることができます。

例えば:

FutureTask<Void> task = new FutureTask<Void>(new Callable<Void>() {
  @Override
  public Void call() throws Exception {
    // Do DB stuff
    return null;
  }
});

Executor executor = Executors.newSingleThreadScheduledExecutor();
executor.execute(task);

try {
  task.get(5, TimeUnit.SECONDS);
}
catch(Exception ex) {
  // Handle your exception
}

例外がスローされますが、プログラムは終了しません。これを手伝ってください。
Ankita、2011年

2
Executorの代わりにExecutorServiceクラスを使用できます。executorを停止するshutdown()メソッドがあります。
2010年

1
エグゼキュータは、Callable / Runnableで具体的に処理しない、スローされた例外を飲み込みます。Runnable / Callableが例外自体をキャッチして処理せず、例外を所有している場合と所有している場合は、ScheduledExecutorServiceをサブクラス化し、afterExecuteをオーバーライドする必要があります(必ずsuper.afterExecute()を呼び出してください)。afterExecuteの2番目の引数は、Runnable / Callableからスロー可能になります
adam

3
    new java.util.Timer().schedule(new TimerTask(){
        @Override
        public void run() {
            System.out.println("Executed...");
           //your code here 
           //1000*5=5000 mlsec. i.e. 5 seconds. u can change accordngly 
        }
    },1000*5,1000*5); 

害虫をコードの上にコピーするだけで問題なく動作します。私は2回「時間」を与えました。最初はこのコードを初めて実行するためのもので、2番目はインターバル時間のためです。
Mahadev Mane

Timerのドキュメントでは、代わりにExecutorフレームワークを使用することを推奨しています。docs.oracle.com/javase/10/docs/api/java/util/Timer.html
Karan Khanna

1

[Android] javaを使用してAndroidにタイマーを実装しようとしている場合。

操作を実行するには、このようなUIスレッドを使用する必要があります。

Timer timer = new Timer();
timer.schedule(new TimerTask() {
           @Override
            public void run() {
                ActivityName.this.runOnUiThread(new Runnable(){
                    @Override
                      public void run() {
                       // do something
                      }        
                });
            }
        }, 2000));
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.