我正在努力学习和学习Java Servlets。我有这个我正在使用的示例,但由于某种原因,页面在遇到同步块时会停止加载。
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);
}
}
网页会将所有内容加载到第29行。 我正在使用GlassFish 4.1.1
我有什么遗失的吗?
答案 0 :(得分:2)
如评论中所述,此代码是荒谬的,并且没有必要将当前日期时间作为实例成员。
在进入synchronized块之前,必须评估synchronized关键字后面的parens中的表达式,以便找出需要获取的锁。每次线程尝试进入块时执行此评估。如果表达式求值为null(由于实例变量尚未初始化,它在此处执行),则抛出NullPointerException。
更改内容线程锁定的变量的值是一个非常糟糕的主意。当执行块的线程更改变量的值时,尝试获取锁的其他线程计算的表达式将解析为与第一个线程当前持有的对象不同的对象,从而使第一个线程保持的锁不相关并允许获取新对象锁的第二个线程,即使第一个线程没有完成也继续进行,如果在synchronized块中有任何重要的事情发生,可能会带来灾难性的后果(与发布的示例不同)。即使你通过确保变量不为null来使其工作,这也是一个很好的避免模式。