3

マルチスレッドを使用するコードで作業しています。関連するコード部分は、次の構造になっています。

try {
    ExecutorService threadExecutor = Executors.newFixedThreadPool(10);

    while (resultSet.next()) {
        name = resultSet.getString("hName");
        MyRunnable worker = new Myrunnable(name);
        threadExecutor.execute(worker);
        Counter++;
    }

    //This never appears
    System.out.println("End while with counter" + Counter);

    threadExecutor.shutdown();
    System.out.println("thread shutdown"); //this never appears

    // Wait until all threads are finish
    while (!threadExecutor.isTerminated()) {
        threadExecutor.awaitTermination(1, TimeUnit.SECONDS);
        System.out.println("inside the thread termination loop."); //I have infinite loop

    }

    System.out.println("Finished all threads"); //never appears

} catch (Exception e) {
    e.printStackTrace();
}

System.out.println("END MAIN");

DBConnection.con.close();

実行機能は確実に終了します。DB の姓が必要な機能を実行し、そのスレッドが終了します。

//The constructor
MyRunnable (String name)  {
    this.name=name;
}

public void run() {
    myclass Obj=new myclass();
    try {
        Obj.myFunction(name);
    } catch (Exception e) {
        System.out.println("Got an Exception: "+e.getMessage());
    }
    System.out.println(" thread exiting" + this.name);
}

私の問題は、私のプログラムがすべてを正しく実行することです。ただし、最後のスレッドで、DB からの姓で「スレッドの終了」が表示されます。しかし、threadexecutor は決してシャットダウンせず、プログラムは無限ループに入ります。

編集

DB から名前を抽出するメインのコードを次に示します。

try {
        st = DBConnection.con.createStatement();

        resultSet = st.executeQuery("select hName from schema1.table1  where checked=1 order by hName");

    } catch (Exception e) {
        System.out.println("DB Error: " + e.getMessage());

    }
4

2 に答える 2

1

何が起こっているのかについての私の最善の推測は次のとおりです。

まず、次の 2 つのコメントが疑われます。

//This never appears
System.out.println("End while with counter" + Counter);

threadExecutor.shutdown();
System.out.println("thread shutdown"); //this never appears

間違っています。実際にはこれらのメッセージを受け取っていると強く思いますが、他のメッセージ (「スレッド終了」メッセージなど) と混ざっているため、それらを見逃すことになります。

第二に、時々Obj.myfunction(name)ハングするのではないかと思います。これは、データベースへの書き戻しを伴う場合に特に発生する可能性がありObj.myfunctionます。ほとんどの場合は正しく動作しますが、ときどき (行数が多いほど) データベースのデッドロックが発生します。したがって、実際には、すべての名前に対して「スレッドが終了しました」というメッセージが表示されるわけではありませんが、リストの途中でそのメッセージが表示されない 1 つまたは 2 つを見つけるのは困難です。

これに該当するかどうかを判断するには、Java プログラムが無限ループに陥っているときに、その Java プログラムのスレッド ダンプを生成します。Unix/Mac では、別のウィンドウを開いて を実行します。kill -3 PIDここで、PIDは Java プロセスのプロセス ID です。Windows では、使用する必要があるキーの組み合わせは Ctrl-Break だと思います。トレッド ダンプで、スレッドプールのワーカー スレッドが への呼び出し内でスタックしているかどうかを確認しますObj.myfunction

ResultSetデータベースのデッドロックの考えられる原因の 1 つは、プログラムの最後でデータベース接続自体を閉じるまで を閉じないことです。への呼び出しを追加します

resultSet.close();

ループが終了した直後while、および についてのメッセージを出力する直前"End while with counter"。そのステートメントを追加した後でもデータベースのデッドロックが発生している場合は、その関数myfunctionが何をしているかに焦点を当てた別の質問をする必要があります。

于 2012-07-15T15:42:12.063 に答える
0

最後のコメントの方が理にかなっています。実行executor.execute(..)しても、スレッドがすぐに実行されるわけではなく、すぐに開始されても、完了するまで「スレッド終了」メッセージは出力されません。その間、メインスレッドは続行され、次のようになります。

  • 印刷System.out.println("End while with counter" + Counter);
  • threadExecutor.shutdown();ほぼすぐに戻るはずのを実行します
  • System.out.println("thread shutdown");ほぼすぐに印刷します。

つまり、スレッドの実行に少し時間がかかる場合は、いずれかのスレッドがタスクを完了する前に、これらの2行が出力されます。

プログラムが終了しない場合は、すでにコメントされているように、何Obj.myFunction(name)が行われているのかが原因である可能性があります-何らかの理由でその呼び出しが終了せず、結果セットにスレッドプールのサイズよりも多くのレコードがある場合、while (!threadExecutor.isTerminated())ループは発生しませんどちらかを終了します。

于 2012-07-16T09:43:14.713 に答える