2012-02-13 54 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