Java 未在servlet中执行同步块
我正在努力学习Java servlet。我使用了这个示例,但是由于某种原因,当页面到达synchronized块时,页面停止加载Java 未在servlet中执行同步块,java,multithreading,servlets,synchronized,Java,Multithreading,Servlets,Synchronized,我正在努力学习Java servlet。我使用了这个示例,但是由于某种原因,当页面到达synchronized块时,页面停止加载 package org.recipe.ch01; import java.io.IOException; import java.io.PrintWriter; import java.util.Date; import javax.servlet.ServletException; import javax.servlet.annotation.WebServl
package org.recipe.ch01;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(name = "CurrentDateAndTime", urlPatterns = {"/CurrentDateAndTime"})
public class CurrentDateAndTime extends HttpServlet
{
Date currDateAndTime;
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter())
{
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet CurrentDateAndTime</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Servlet CurrentDateAndTime at " + request.getContextPath() + "</h1>");
out.println("<br/>");
synchronized (currDateAndTime)
{
currDateAndTime = new Date();
out.println("The current date and time is: " + currDateAndTime);
}
out.println("</body>");
out.println("</html>");
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
processRequest(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
processRequest(request, response);
}
}
package org.recipe.ch01;
导入java.io.IOException;
导入java.io.PrintWriter;
导入java.util.Date;
导入javax.servlet.ServletException;
导入javax.servlet.annotation.WebServlet;
导入javax.servlet.http.HttpServlet;
导入javax.servlet.http.HttpServletRequest;
导入javax.servlet.http.HttpServletResponse;
@WebServlet(name=“CurrentDateAndTime”,urlPatterns={”/CurrentDateAndTime“})
公共类CurrentDateAndTime扩展了HttpServlet
{
日期和时间;
受保护的void processRequest(HttpServletRequest请求,HttpServletResponse响应)引发ServletException,IOException
{
setContentType(“text/html;charset=UTF-8”);
尝试(PrintWriter out=response.getWriter())
{
out.println(“”);
out.println(“”);
out.println(“Servlet CurrentDateAndTime”);
out.println(“”);
out.println(“”);
println(“Servlet CurrentDateAndTime at”+request.getContextPath()+”);
out.println(“
”);
已同步(currDateAndTime)
{
currDateAndTime=新日期();
out.println(“当前日期和时间为:“+currDateAndTime”);
}
out.println(“”);
out.println(“”);
}
}
@凌驾
受保护的void doGet(HttpServletRequest请求,HttpServletResponse响应)抛出ServletException,IOException
{
processRequest(请求、响应);
}
@凌驾
受保护的void doPost(HttpServletRequest请求、HttpServletResponse响应)引发ServletException、IOException
{
processRequest(请求、响应);
}
}
该网页将加载到第29行的所有内容。
我使用的是GlassFish 4.1.1
有什么我遗漏的吗?如注释中所述,此代码毫无意义,将当前日期时间作为实例成员没有意义 在进入同步块之前,必须计算synchronized关键字后面的参数中的表达式,以确定需要获取的锁。每次线程尝试进入块时都会执行此计算。如果表达式的计算结果为null(此处为null,因为实例变量尚未初始化),则会抛出NullPointerException
更改线程锁定其内容的变量的值是一个非常糟糕的主意。当执行块的线程更改变量的值时,试图获取锁的其他线程计算的表达式将解析为与第一个线程当前持有的对象不同的对象,使第一个线程持有的锁不相关,并允许第二个线程获取新对象的锁并继续,即使第一个线程没有完成,如果同步块中发生了任何重要的事情(与发布的示例不同),则可能导致灾难性的后果。即使通过确保变量不为null来实现这一点,这也是一个很好的避免模式。
currDateAndTime
为null
synchronized
语句将NPE抛出null
。看看你的日志。为什么currDateAndTime
甚至需要一个实例字段呢?就是这样!这是一个例子,没有理由这样做。我想他们只是想展示synchronized是如何工作的,所有servlet都是线程化的。@SotiriosDelimanolis是正确的。然而,我很好奇为什么在这种情况下你甚至会使用同步块。我只想删除这个块。我还将currDateAndTime设置为局部变量,而不是类成员。