Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Servlet中的静态变量行为_Java_Multithreading_Servlets_Static - Fatal编程技术网

Java Servlet中的静态变量行为

Java Servlet中的静态变量行为,java,multithreading,servlets,static,Java,Multithreading,Servlets,Static,我正在开发一个JavaServlet,它在运行时在新线程中启动不同的对象方法。这些线程应该访问一个描述特定servlet实例的变量,比如jobId。因此,我将jobId变量声明为static。servlet构造函数正在为每个servlet实例(调用)计算该值。 我想知道,如果servlet同时被调用了几次,那么静态jobId变量将在调用之间共享,这意味着一些线程将获得错误的jobId,或者每次调用只计算一次,因此特定servlet启动的线程将使用为该特定servlet计算的jobId(这是我想要

我正在开发一个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实现该接口,以便在每次请求期间强制创建。但这是一个糟糕的设计,而且成本不必要。这也是弃用该接口的原因

另见:

servlet规范中没有定义servlet的实例化策略(据我所知,任何人),但通常的行为似乎是每个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:它们无论如何都是不可变的,所以这很好。只有当您将局部变量分配给实例变量声明时才会出现问题。使用常量已经不可能了。