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

问题描述:

我在使用多线程的代码中工作。相关代码的结构如下:使用线程池退出线程的无限循环

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

编辑

这里是主要的,它可以提取数据库名称的代码。

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

    } 
+3

你说这个消息'结束while计数器结束'永远不会出现。所以你的程序永远不会退出while循环。然后它听起来不像一个'ExecutorService'相关的问题。 – 2012-07-14 09:14:34

+0

请注意,如果从数据库读取少量记录,则线程结束并且程序终止。但是当数字增加时,程序永远不会终止(或者至少长时间停留在循环中(+5分钟),直到我手动终止它) – 2012-07-14 09:15:16

+1

然后它可能与'Obj.myFunction(name)'是什么有关如果它永远不会结束,并且结果集有超过10条记录(池的大小),则while循环永远不会结束。 – assylias 2012-07-14 09:16:36

这里是发生了什么事我最好的猜测:

首先,我怀疑,这两个意见:

//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上,通过打开另一个窗口并执行kill -3 PID来完成此操作,其中PID是您的java进程的进程ID。在Windows中,我认为您需要使用的组合键是Ctrl-Break。在胎面转储中,查看线程池的工作线程是否卡在Obj.myfunction的调用中。

数据库死锁的一个可能的来源是,在程序结束时关闭数据库连接本身之前,您不要关闭ResultSet。我想你的while循环结束之后添加一个调用

resultSet.close(); 

,你打印出来之前你对"End while with counter"消息。如果即使在添加该语句后仍然发生数据库死锁,那么您将不得不问一个关于该功能myfunction正在做什么的不同问题。

+0

对于数据库,我同步查询: Query =“insert into table values(default,?,?)'和准备好的语句:'preparedStmt = DBConnection.con.prepareStatement(Query);'但是我不同步插入并执行:'preparedStmt.setString(1,token);''和'preparedStmt.executeUpdate();'。你是否看到这个问题? – 2012-07-16 19:33:00

+0

我不认为你明白什么可能导致数据库锁定 - 但如果你在工作线程中调用的是写入*相同的表*,那么你最初选择的是_really_,只要while循环结束就想关闭你的'resultSet'。 – 2012-07-17 14:39:13

+0

No.我不想写在同一张桌子上,他们是两张不同的表格,我之前的问题是一般性的,因为我从第一个位置对此有所怀疑,我会尽量关闭结果集并尽快更新 – 2012-07-17 16:14:20

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

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

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

现在,如果你的程序不退出,这是最有可能的,因为已经评论的原因是什么Obj.myFunction(name)是干什么的, - 如果调用从来没有出于某种原因结束,你的结果集比你的线程池的大小更多的记录,while (!threadExecutor.isTerminated())循环将永远不会结束。

+0

那么,这是否意味着,我必须将线程池的大小设置为记录编号?例如:如果我有1000条记录,我应该将我的池大小设置为1000? – 2012-07-16 14:18:57

+0

不,这意味着您必须了解阻止线程退出并修复它的原因。丹尼尔马丁在他的回答中提出了一些想法。没有更多信息,我们无法真正帮助更多。再一次,如果你设法创建一个能够再现行为的SSCCE,那么找出问题的原因将会容易得多。 – assylias 2012-07-16 14:22:11

+0

该函数执行SSL握手。程序在单线程模式下不会遇到问题。我确定该功能结束。现在,请再提一个问题。如果我想在打印'System.out.println(“在线程终止循环内部”)的循环中输出'name'的值,''。我怎样才能做到这一点?当我打印变量'worker.name'时,我认为这个特定的线程在'循环内部'时给了'name'的值,但我总是从DB中检索到最后一个'name'。 – 2012-07-18 23:40:00