2016-08-24 3 views
1

APIをクエリしてレポートを作成し、そのレポートを5分後に読み込みたいとします。私はそのためにScheduledExecutorServiceを使用したいと思います。エグゼクティブにスレッドをブロックさせたくないので、新しいスレッドを作成していますが、これが正しい方法かどうかはわかりません。ここに私のコードは次のとおりです。新しいスレッドでスケジュールを実行する

Thread thread = new Thread() { 
     public void run() { 
      log.info("Starting..."); 
      new RequestReport().runScheduledTask(requestId); 
     } 
    }; 
thread.start(); 

private void runScheduledTask(String requestId) { 
    log.info("Starting five-minute countdown now..."); 
    ScheduledFuture<?> countdown = scheduler.schedule(() -> { 
     try { 
      new GetReportList().run(requestId); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    }, 5, TimeUnit.MINUTES); 

    try { 
     countdown.get(); 
    } catch (InterruptedException | ExecutionException e) { 
     log.info("catched Exception"); 
     e.printStackTrace(); 
    } 
    scheduler.shutdown(); 
} 

は、5分後に別の機能を実行するためのより良い方法はありますか?私はこれをやっているのですか?私は何を変えるべきですか?

ところで、私は春を使用しています - それを改善できるものはありますか?

+0

Springを使用している場合は、メソッド呼び出しをスケジュールするために '@ Scheduled' [annotation](https://spring.io/guides/gs/scheduling-tasks/)を使用することもできます。 –

+0

しかし、私はそれを動的にすることはできますか?私は5分後にタスクを実行する必要があります - 実行時間はプログラムの開始時に知られていません。 @SurajBajaj –

+0

@ J.Doeあなたの 'while(!countdown.isDone()){}'ビジーループは本当に悪い考えです。 – Kayaman

答えて

4

ScheduledExecutorServiceに言われたクラスのインスタンスに沿って渡すことができますあなたはそれを間違って使用します:

まず、Threadを作成する必要はありません。機能に何も追加せず、リソースを浪費します。

第2に、shutdown()を呼び出した後、schedulerはタスクを受け付けなくなります。複数のレポートを生成する必要がある場合は、これが問題になります。

第3に、タスクの完了後にコードが何もしないので、get()を呼び出す必要はありません。

だから、あなたが必要とする唯一のコードは次のとおりです。

scheduler.schedule(() -> { 
    try { 
     new GetReportList().run(requestId); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
}, 5, TimeUnit.MINUTES); 

それは、タスクのスケジュールを設定し、すぐにスレッドを解放します。タスクは5分後に別のスレッドで実行され、そのスレッドはschedulerによって管理されます。

予約タスク(状態の確認、キャンセルなど)が必要な場合は、をschedule()から取得してどこかに保存しますが、質問のコードに基づいて必要はありません。

+0

完璧、ありがとうございます。それは私が必要としていたものでした!春は 'get()'が呼び出されるまで開始されませんでしたが、あなたの説明ははるかに意味があります... –

+0

@ J.Doe、少し増やしてください。 "春はget()と呼ばれていました"?私はこのコードが何らかの形でSpringに影響するとは思わない。それが始まるのを妨げる何か他のものだったのでしょうか? 'get()'を呼び出すと、スレッドはブロックし、タスクの完了を待ちます(少なくとも5分かかる)。あなたの 'GetReportList.run()'は何も返さないので、あなたのプログラムでは必要ないと思います。 –

+0

はい、あなたの言ったとおりです。私があなたが提案した変更を行う前に私は意味しました。今は完璧に動作しますが、ブロックされたときに関数内に 'get()'があったとき(新しいスレッドを作成せずに)はしませんでした。あなたの答えは完璧に働きます! –

0

あなたは、コードの詳細「正しい」になりたい場合は、あなたがRunnableインターフェイスを実装して独自のクラスにRequestReportを分離し、スレッドのコンストラクタ

+2

クラスは、クラスのインスタンスを 'run()'する意味を明白に明確に説明している場合にのみ、 'Runnable'を実装する必要があります。 RequestReportを実行するとはどういう意味ですか?それはレポートを生成することを意味しますか? _print_レポートを意味するのでしょうか? _and_レポートを生成しますか?一体何か?単なる明白な意味がない場合は、IMOでは、ラムダ式で、またはOPの例のように匿名の内部クラスで 'run()'メソッドを実装する方が良いでしょう。 –

関連する問題