关于servlet的线程安全性有很多问题,但我想问一下servlet使用的其他类。
在正常的应用程序中,servlet类也使用其他普通类(我的应用程序),就像在MVC中一样。所以我的问题是我应该将模型类中的所有函数声明为synchronized
假设我有2个servlet和使用类Dog和Cat。这两个类都有一些静态和非静态函数以及静态和非静态变量。
这些方法使用数据库连接来显示内容,我为此代码获得了nullpointerexception
try {
Connection con = DriverManager.getConnection(url, user, pass);
Statement stmt = con.createStatement();
select = "SELECT * FROM table";
java.sql.ResultSet result = stmt.executeQuery(select);
while(result.next())
{
do something
}
}
catch (SQLException e) {
e.printStackTrace();
}
finally {
if (con != null)
try {
con.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
令我惊讶的是我在行try { con.close(); } : nullPointerException
中得到了例外
据我所知,我已经检查if (con != null)
con
应该{{1}}
不是空的。
所以,
答案 0 :(得分:3)
在servlet中,它通常是糟糕的设计......并且可能是一个错误......有静态变量。但是如果你确实使用(并且需要使用)静态变量,那么访问和更新它们的代码就需要正确同步。 (Servlet代码在多个线程上执行......除非您通过仅配置一个工作线程来阻塞Web容器框架。)
如果您正确地执行此操作,则将方法声明为synchronized
是实现此目的的一种方法。
然而......
简单地将方法声明为synchronized
是不可能的。在开始添加同步之前,您需要了解代码的预期并发模式。无意识地添加synchronized
会导致并发瓶颈和潜在的死锁。 (并且你仍然可以遇到线程安全问题......如果互斥的粒度不适合问题。)
我同意@Roman C的答案。您不应该尝试跨多个请求共享相同的数据库连接...如果这是您实际正在做的事情。我建议你研究一下使用数据库连接池。
答案 1 :(得分:1)
不要在其他课程中使用静态。那你就不应该对线程安全感到害怕,JDBC API会关注它。但是如果你在servlet之间共享一些对象,比如在某些上下文中,那么你应该同步容器来访问它。这是使用一些基于servlet技术的框架的原因,这些框架是为了帮助您更好地使用其他对象并以线程安全的方式使用它们而创建的。原始servlet是强大的,但你必须解决你遇到的问题,进一步尝试重新发明轮子。
关于异常捕获,它可能会抛出第一个语句,因此con
对象仍未初始化。手动管理连接(如果有的话)不是一个好方法,因为你遇到了同样的问题来同步它们。作为JDBC的标准,为您提供了通过池管理连接的API,因此您不必重新发明轮子,提供您自己的同步方法。