2

次のコードがあります。

public void run() 
{
     try 
     {
         logger.info("Looking for new tasks to fetch...  ");
         // definitions ..

         for(Task t: tasks)
         {
             logger.info(" Task " + t.getId() + " is being fetched ");
            // processing ... fetching task info from db using some methods
         }
         Thread.sleep(FREQUENCY);
         //t.start();
     } catch (Exception e) 
     {
         logger.info("FetcherThread interrupted: "+e.getMessage());
     }
}

特定の時間「FREQUENCY」の間スレッドをスリープさせてから、再び動作させようとしています。このコードをEclipseで実行すると、スレッドは1回だけ動作し、その後何も起こらず、プロセスが終了します。ステートメントからコメントを削除すると: t.start()、「FetcherThread interrupted: null」が表示されます。誰が私が間違っているのか教えてもらえますか?

注意: スレッドを常に動作させたいのですが、定期的にフェッチします (5 分ごとなど)。

4

9 に答える 9

7

そのコードには、あらゆる種類のループがありません。

スレッドは実際にあなたが指示したことを実行しているようです: スレッドはすべてのタスクを実行し、少しの間スリープします。その後、行う作業がなくなり、終了します。これに対処するには、複雑さと正確さの昇順でいくつかの方法があります。

  1. これに対処する単純な (そして素朴な) 方法は、try-catch ブロックを無限ループ ( while(true) { ... }) でラップすることです。このようにして、スレッドがスリープを終了した後、ループして先頭に戻り、すべてのタスクを再度処理します。

  2. ただし、スレッドを停止することは基本的に不可能であるため、これは理想的ではありません。より良いアプローチは、ブール フィールド (例: boolean running = true;) を宣言し、ループを に変更することwhile(running)です。このようにして、スレッドを終了させる方法があります (たとえば、 に設定するメソッドを公開runningfalseます)。詳細については、Sun のWhy is Thread.stop() deprecated記事を参照してください。

  3. さらに一歩遡ると、低すぎるレベルでこれを行おうとしている可能性があります。スリープとスケジューリングは、実際には の仕事の一部ではありませRunnable。私が採用する実際の解決策は、スリープ状態を取り除き、すべてのタスクを処理してから終了する Runnable 実装を用意することです。次に、ScheduledExecutorServiceを作成し、「バニラ」ランナブルをエグゼキュータに送信します。このようにして、タスクを定期的に実行するのがエグゼキュータの仕事です。

最後のソリューションは、エンジニアリングの観点から理想的です。ジョブを一度実行して終了するだけのクラスがあります。これは、ジョブを実行したいときにいつでも他のコンテキストで使用でき、非常にうまく構成できます。任意のタスクのスケジューリングをジョブとする executor サービスがあります。繰り返しますが、将来、さまざまなタイプのRunnableorCallableを this に渡すことができ、スケジューリング ビットも同様に実行されます。そして、おそらくすべての最も良い部分は、スケジューリングに関するものを自分で書く必要がないことですが、これをすべて実行する標準ライブラリのクラスを使用できます (したがって、大部分の自家製の同時実行コードとは異なり、バグはすでに解決されています)。

于 2012-05-16T10:17:26.350 に答える
1

タスク スケジューリングは、Java で最高レベルのサポートを提供します。再発明しないでください。実際、(旧式) と(新)の2 つの実装があります。それらを読んで、それらに基づいてアプリを設計してください。TimerScheduledExecutorService

于 2012-05-16T10:21:08.757 に答える
0

ScheduledExecutorServiceJavadoc )を試すことができます。そして、私たちそれscheduleAtFixedRateは、それです:

指定された初期遅延の後に最初に有効になり、その後指定された期間で有効になる定期的なアクションを作成して実行します。つまり、実行はinitialDelay、initialDelay + period、initialDelay +2*期間の後に開始されます。

于 2012-05-16T10:22:25.243 に答える
0

ワークフローを繰り返すには、ある種のループが必要です。制御フローはどのようにしてフェッチ部分に戻るのでしょうか?

于 2012-05-16T10:17:43.510 に答える
0

コードをループ内に置くことができます。(しばらくの間かもしれません)

while(condition) // you can make it while(true) if you want it to run infinitely.
{
      for(Task t: tasks)
     {
         logger.info(" Task " + t.getId() + " is being fetched ");
        // processing ... fetching task info from db using some methods
     }
     Thread.sleep(FREQUENCY);
}

あなたの場合、タスクループを実行し、しばらくスリープしてスレッドを終了するとどうなりますか。

于 2012-05-16T10:17:50.940 に答える
0

他の人がここで述べているように、スレッドをループに入れます。

Thread.startを複数回呼び出すことは違法であり、それが例外を受け取る理由です。

複数のスレッドを生成する場合は、開始するスレッドごとに1つのThreadオブジェクトを作成します。

http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html#start()を参照してください

于 2012-05-16T10:20:05.047 に答える
0
public void run() 
{
    while (keepRunning) {
        try 
        {
            logger.info("Looking for new tasks to fetch...  ");
            // definitions ..

            for(Task t: tasks)
            {
                logger.info(" Task " + t.getId() + " is being fetched ");
                // processing ... fetching task info from db using some methods
                t.start();
            }
            Thread.sleep(FREQUENCY);

        } catch (Exception e) {
            keepRunning = false;
            logger.info("FetcherThread interrupted: "+e.getMessage());
        }  
    }
}

メンバー呼び出しkeepRunningをメインスレッドに追加し、それをfalseに設定するためのアクセサーメソッドを実装します(スレッドによるタスクの実行を停止する必要がある場所から)

于 2012-05-16T10:20:05.883 に答える
0

別のスレッドでタスクを実行してみてください。

于 2012-05-16T10:16:49.260 に答える
0

スリープを無限ループに入れる必要があります(または、スリープしたいときまで指定する条件があります)。現在、sleep メソッドは run メソッドの最後に呼び出され、観察した動作は正しいです。次のデモ コードは、1 秒間スリープした後、コンソールに "Sleep" を出力します。それが役に立てば幸い。

import java.util.concurrent.TimeUnit;

public class Test implements Runnable {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Test t = new Test();
        Thread thread = new Thread(t);
        thread.start();
    }

    public void run() {
        try {
            // logger.info("Looking for new tasks to fetch...  ");
            // definitions ..

            // for(Task t: tasks)
            // {
            // logger.info(" Task " + t.getId() + " is being fetched ");
            // // processing ... fetching task info from db using some methods
            // }
            while (true) { // your condition here
                TimeUnit.SECONDS.sleep(1);
                System.out.println("Sleep");
            }

            // t.start();
        } catch (Exception e) {
            // logger.info("FetcherThread interrupted: "+e.getMessage());
        }
    }
}
于 2012-05-16T10:16:52.703 に答える