关于servlet的线程安全问题有很多,但是我想问一下servlet使用的其他类。
在普通应用程序中,servlet 类也使用其他普通类(我的应用程序使用),就像在 MVC 中一样。所以我的问题是我是否应该将模型类中的所有函数声明为同步
假设我有 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
应该
不为空。
那么,
在 Servlet 中,使用静态变量通常是糟糕的设计……并且可能是一个错误……。 但是,如果您确实使用(并且需要使用)静态变量,那么访问和更新它们的代码将需要正确同步。 (Servlet 代码在多个线程上执行......除非您通过仅配置一个工作线程来阻碍 Web 容器框架。)
如果做得正确,将方法声明为
synchronized
是实现此目的的一种方法。
但是...
简单地将方法声明为
synchronized
是一个坏主意。 在开始添加同步之前,您需要了解代码的预期并发模式。 盲目添加 synchronized
可能会导致并发瓶颈和潜在的死锁。 (如果互斥的粒度不适合该问题,您仍然可能会遇到线程安全问题。)
我同意@Roman C的回答。 您不应该尝试在多个请求之间共享相同的数据库连接......如果这就是您实际上正在做的事情。 我建议您考虑使用数据库连接池。
不要在其他类中使用静态。那么你不应该担心线程安全,JDBC API 会关心它。但是,如果您在 servlet 之间共享某些对象,例如在某些上下文中,那么您应该同步可以访问它的容器。这是使用一些基于 servlet 技术的框架的原因,这些框架是为了帮助您更好地使用其他对象并以线程安全的方式使用它们而创建的。原始 Servlet 功能强大,但您必须解决自己进一步尝试重新发明轮子时遇到的问题。
关于异常捕获,它可能会在第一条语句中抛出,因此
con
对象仍然没有初始化。手动管理连接(如果有)不是一个好方法,因为您在同步它们时遇到了同样的问题。作为 JDBC 标准,您可以通过池提供 API 来管理连接,因此您无需重新发明轮子来提供自己的同步方法。