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();

run 函数肯定会结束。我的数据库中的姓氏执行所需的功能,其线程结束。

//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);
}

我的问题是我的程序正确执行了所有内容,除了在最后一个线程中,我看到带有数据库中姓氏的“线程退出”。但是线程执行器永远不会关闭,程序进入无限循环。

编辑

这是从数据库中提取名称的主要代码。

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

这是我对正在发生的事情的最佳猜测:

首先,我怀疑这两条评论:

//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涉及写回数据库,这尤其有可能——它在大多数情况下都能正常工作,但时不时地(更可能是更多的行)你会遇到数据库死锁。因此,事实上,您不会为每个名称都收到“线程已退出”消息,但是在列表中间找到一两个没有给您该消息的消息将是困难的。

为了确定是否是这种情况,我将在您的 Java 程序处于无限循环时生成它的线程转储。在 Unix/Mac 上,您可以通过打开另一个窗口并执行 来执行此操作, java 进程的进程 IDkill -3 PID在哪里。PID在 Windows 中,我认为您需要使用的组合键是 Ctrl-Break。在线程转储中,查看线程池的工作线程是否卡在对Obj.myfunction.

ResultSet数据库死锁的一种可能来源是您在程序结束时关闭数据库连接本身之前不会关闭您的。我会添加一个电话到

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();which 应该几乎立即返回
  • System.out.println("thread shutdown");也几乎立即打印。

换句话说,如果您的线程正在做的任何事情都需要一点时间,那么这两行将在任何线程完成其任务之前打印出来。

现在,如果您的程序没有退出,正如已经评论过的那样,很可能是因为Obj.myFunction(name)正在执行的操作 - 如果由于某种原因该调用永远不会结束,并且您的结果集的记录多于线程池的大小,则while (!threadExecutor.isTerminated())循环将永远不会结束。

于 2012-07-16T09:43:14.713 回答