Java Servlet中的静态变量行为
我正在开发一个JavaServlet,它在运行时在新线程中启动不同的对象方法。这些线程应该访问一个描述特定servlet实例的变量,比如jobId。因此,我将jobId变量声明为static。servlet构造函数正在为每个servlet实例(调用)计算该值。 我想知道,如果servlet同时被调用了几次,那么静态jobId变量将在调用之间共享,这意味着一些线程将获得错误的jobId,或者每次调用只计算一次,因此特定servlet启动的线程将使用为该特定servlet计算的jobId(这是我想要的工作方式)。 有什么想法吗?Java Servlet中的静态变量行为,java,multithreading,servlets,static,Java,Multithreading,Servlets,Static,我正在开发一个JavaServlet,它在运行时在新线程中启动不同的对象方法。这些线程应该访问一个描述特定servlet实例的变量,比如jobId。因此,我将jobId变量声明为static。servlet构造函数正在为每个servlet实例(调用)计算该值。 我想知道,如果servlet同时被调用了几次,那么静态jobId变量将在调用之间共享,这意味着一些线程将获得错误的jobId,或者每次调用只计算一次,因此特定servlet启动的线程将使用为该特定servlet计算的jobId(这是我想要
非常感谢!静态意味着每个实例将访问相同的值。
因此,连接到servlet的每个用户都将访问相同的值。当两个或更多用户连接在一起时,您的jobId可能是错误的 您必须在每个连接中获取自己的值,并将其存储到其他位置
资源:
至于如何工作,您可以将jobId放在HttpSession中,然后每个用户都有自己的副本。一个servlet在webapp启动时只创建一次,并在所有请求之间共享。静态与否,每个类/实例变量都将在所有请求/会话之间共享。您不希望分配请求/会话n作用域数据。而是将它们声明/分配为methodlocal变量
public class MyServlet extends HttpServlet {
private static Object thisIsNotThreadsafe;
private Object thisIsAlsoNotThreadsafe;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Object thisIsThreadsafe;
thisIsNotThreadsafe = request.getParameter("foo"); // BAD! Shared among all requests.
thisIsAlsoNotThreadsafe = request.getParameter("foo"); // BAD! Shared among all requests.
thisIsThreadsafe = request.getParameter("foo"); // Good.
}
}
存在遗留的已弃用的接口,您可以让servlet实现该接口,以便在每次请求期间强制创建。但这是一个糟糕的设计,而且成本不必要。这也是弃用该接口的原因
另见:
如果我是你,我会考虑把JooID作为一个参数发送到<代码> Runnaby<代码> s,你正在运行线程。例如,代替这个:
public class HelloWorld extends HttpServlet {
private static long jobId;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
jobId = Long.parseLong(request.getParameter("jobid");
new Thread(new Worker()).start();
}
static class Worker implements Runnable {
@Override
public void run() {
doSomethingWith(jobId);
}
}
}
重构静态变量,如下所示:
public class HelloWorld extends HttpServlet {
// private static long jobId; -- delete, no longer needed
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long jobId = Long.parseLong(request.getParameter("jobid"); // local variable
new Thread(new Worker(jobId)).start(); // send jobId as parameter
}
static class Worker implements Runnable {
private final long jobId; // non-static; every instance has one
public Worker(long jobId) { // allow injection of jobId
this.jobId = jobId;
}
@Override
public void run() {
doSomethingWith(jobId); // use instance variable instead of static
}
}
}
更容易阅读,没有并发问题-纯赢。真的,避免使任何可变
静态
(包括单例)。这在servlet规范中肯定有描述。请阅读第2.3章。此外,在servlet中生成线程必须非常小心。只要OP的功能要求不明确,并且他的技能水平低,我就不建议这样做。这只会导致更多的混乱和麻烦。可能只是存储在会话中pe或作为请求参数传递/保留已经足够了。如果我使用私有静态最终变量呢?用于常量值。这会很好吗?@Ommadawn:它们无论如何都是不可变的,所以这很好。只有当您将局部变量分配给实例变量声明时才会出现问题。使用常量已经不可能了。