2012-02-13 88 views
0

我試圖使用自己的連接池來處理數據庫連接,但由於某種原因它似乎被阻塞,即使我使用了一個線程,有人可以幫我指出我的錯誤。帶線程的Java Servlet阻塞?

這是帶有線程類的servlet代碼。

protected void processRequest(HttpServletRequest request, 
     HttpServletResponse response) throws ServletException, IOException { 
    // PrintWriter out = response.getWriter(); 
    OutputStream ostream = response.getOutputStream(); 
    PrintStream out = new PrintStream(ostream, true, "UTF8"); 

    try { 

     response.setContentType("text/html"); 
     String test = request.getParameter("test"); 
     System.out.println("Received text: " + test); 

     if(test.equals("free")) 
     { 
      for (int i = 0; i < list.size(); i++) { 
       dbcm.freeConnection(list.get(i)); 
      } 
      list.clear(); 
     }else 
     { 
      GetConnThread gct = new GetConnThread(test, dbcm); 
      gct.start(); 
     } 

    } catch (Exception e) { 
     e.printStackTrace(); 
     out.println("fail"); 
    } finally { 
     out.close(); 
    } 

} 



private class GetConnThread extends Thread 
{ 
    private String test; 
    private DBConnectionManager dbcm; 

    public GetConnThread(String test, DBConnectionManager dbcm) 
    { 
     this.test = test; 
     this.dbcm = dbcm; 
    } 

    public void run() 
    { 
     try { 
      Connection conn = dbcm.getConnection(test); 
      list.add(conn);    
      System.out.println(conn); 
      System.out.println("list size: " + list.size()); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

    } 
} 

這是DBConnectionManager

public synchronized Connection getConnection(String test) throws CGFatalException { 
     Connection con = null; 
     boolean connectionIsValid = false; 
     if (freeConnections.size() > 0) { 

      con = (Connection) freeConnections.firstElement(); 
      freeConnections.removeElementAt(0); 

      connectionIsValid = validateConnection(con); 
      if (connectionIsValid == false) { 
       con = getConnection(test); 
      } 
     } else if (maxConn == 0 || checkedOut < maxConn) { 
      con = newConnection(); 
      connectionIsValid = validateConnection(con); 
      if (connectionIsValid == false) { 
       con = getConnection(test); 
      } 
     }else 
     { 
      System.out.println("No available connections for " + test + ", try again in 2 secs...."); 
      try { 
       Thread.sleep(2000); 
       con = getConnection(test); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 

     if (con != null && connectionIsValid == true) { 
      checkedOut++; 
     } 
     System.out.println("checkedOut: " + checkedOut); 
     System.out.println("maxConn: " + maxConn); 
     return con; 
    } 

我設置最大連接到2,從而後我調用servlet它進入這行代碼的第三時間getConnection方法:

System.out.println("No available connections for " + test + ", try again in 2 secs...."); 

當我第四次說它時,我期待

System.out.println("No available connections for " + test + ", try again in 2 secs...."); 

作爲一個單獨的線程開始,但第三個調用似乎阻止它,因爲我希望調用「free」來清除連接並且一切都恢復正常,所以預計會出現無限循環。

+0

我想你需要提供更多的信息 - 可能是一個日誌文件。你說_無限循環是期待的,但是你沒有向我們展示一個無限循環。第三個電話似乎阻止了它,但沒有證據表明這一點,所以我們不得不依靠你的猜測工作。 – Tim 2012-02-13 03:25:00

+0

「無限循環」是由遞歸調用在thread.sleep(2000)之後試圖獲得「空閒」連接引起的。 – Maurice 2012-02-13 03:27:58

+1

除非是純粹的愛好目的,否則如果您已經不知道線程和併發性如何工作,請執行** not ** homegrow連接池。去選擇一個現有的連接池庫。每個自我推崇的servletcontainer都附帶內置的連接池設施,包括Tomcat。利用它。真。連接池是一個非常重要的健康Web應用程序的人工製品,你不想在0理解的情況下自行生成。 – BalusC 2012-02-13 04:40:12

回答

2

您的getConnection方法已同步。每個其他線程將阻止該鎖的獲取,直到「第三個」請求成功獲得連接並繼續。

+0

是的,這是正確的我剛剛刪除它並測試。如果我刪除了「同步化」關鍵詞,您是否預見到我可能面臨的連接干擾計數器的主要問題? – Maurice 2012-02-13 03:40:06

+0

看起來像沒有同步就會破裂,是的。而不是同步整個方法使用java.util.concurrent.locks.Lock,以便在睡覺之前釋放鎖。 – Affe 2012-02-13 03:46:41

+0

好的,謝謝你將會看到這個。新的鎖。 – Maurice 2012-02-13 04:03:07