使用线程池退出线程的无限循环

时间:2012-07-14 09:00:35

标签: java mysql multithreading

我正在使用多线程的代码。相关的代码片段采用以下结构:

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

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

//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永远不会关闭,程序进入无限循环。

修改

以下是main中从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());

    }

2 个答案:

答案 0 :(得分: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涉及写回数据库,这种情况尤其可能 - 它在大多数情况下都会正常工作,但是时不时(更可能有更多行)会导致数据库死锁。所以,事实上,你没有得到每个名称的“Thread exited”消息,但是在列表中间找到一个或两个没有给你那个消息的消息将会发生很难。

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

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

的调用
resultSet.close();

while循环结束后,就在您打印出有关"End while with counter"的消息之前。如果您在添加该语句后仍然看到发生数据库死锁,那么您将不得不提出一个不同的问题,重点关注该函数myfunction正在做什么。

答案 1 :(得分:0)

您的上一条评论更有意义:当您运行executor.execute(..)时,并不意味着该线程将立即运行,即使它立即启动,也不会打印“线程退出”消息直到它完成。与此同时,主要线程继续并将:

  • print System.out.println("End while with counter" + Counter);
  • 运行几乎立即返回的threadExecutor.shutdown();
  • 几乎立即打印System.out.println("thread shutdown");

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

现在,如果你的程序没有退出,那么很可能就像已经评论过的那样,因为Obj.myFunction(name)正在做什么 - 如果这些调用由于某种原因永远不会结束,并且你的结果集的记录大于你的线程池,while (!threadExecutor.isTerminated())循环也永远不会结束。