同步块未在 servlet 中执行
synchronized block not executing in servlet
我正在尝试研究和了解 Java Servlet。我有一个正在使用的示例,但由于某种原因,页面在遇到同步块时停止加载。
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
有什么我遗漏的吗?
如评论中所述,此代码毫无意义,将当前日期时间设为实例成员毫无意义。
在进入同步块之前,必须对同步关键字后面的括号中的表达式求值,以确定需要获取什么锁。每次线程尝试进入块时都会执行此评估。如果表达式的计算结果为 null(它在这里这样做是因为实例变量尚未初始化)则抛出 NullPointerException。
更改其内容线程正在锁定的变量的值是一个非常糟糕的主意。当执行该块的线程更改变量的值时,其他试图获取锁的线程评估的表达式将解析为与第一个线程当前持有的对象不同的对象,从而使第一个线程持有的锁无关紧要并允许第二个线程获取新对象的锁并继续,即使第一个线程未完成,如果同步块中发生任何重要事情(与发布的示例不同),可能会造成灾难性后果。即使您通过确保变量不为 null 来使其工作,也是避免这种模式的好方法。
我正在尝试研究和了解 Java Servlet。我有一个正在使用的示例,但由于某种原因,页面在遇到同步块时停止加载。
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
有什么我遗漏的吗?
如评论中所述,此代码毫无意义,将当前日期时间设为实例成员毫无意义。
在进入同步块之前,必须对同步关键字后面的括号中的表达式求值,以确定需要获取什么锁。每次线程尝试进入块时都会执行此评估。如果表达式的计算结果为 null(它在这里这样做是因为实例变量尚未初始化)则抛出 NullPointerException。
更改其内容线程正在锁定的变量的值是一个非常糟糕的主意。当执行该块的线程更改变量的值时,其他试图获取锁的线程评估的表达式将解析为与第一个线程当前持有的对象不同的对象,从而使第一个线程持有的锁无关紧要并允许第二个线程获取新对象的锁并继续,即使第一个线程未完成,如果同步块中发生任何重要事情(与发布的示例不同),可能会造成灾难性后果。即使您通过确保变量不为 null 来使其工作,也是避免这种模式的好方法。