2012-07-14 109 views
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(); 

運行函數肯定會結束。我的數據庫中的姓氏執行所需的功能,並且其線程結束。

//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

回答

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上,通過打開另一個窗口並執行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

0

您最後的評論更有意義:當您運行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