>

실행중인 동안 새로운 스레드에서 다른 객체 메소드를 시작하는 Java 서블릿을 개발 중입니다. 이러한 스레드는 jobServ와 같은 특정 서블릿 인스턴스를 설명하는 변수에 액세스해야합니다. 이런 이유로 나는 jobId 변수를 정적으로 선언했다. 서블릿 생성자는 각 서블릿 인스턴스 (호출)에 대해이 값을 계산합니다. 서블릿이 동시에 몇 번 호출되면 정적 jobId 변수가 호출간에 공유되므로 일부 스레드가 잘못된 jobId를 얻거나 각 호출에 대해 한 번씩 계산됩니다. 시작된 특정 서블릿은이 특정 서블릿에 대해 계산 된 jobId를 사용합니다 (작동 방식). 어떤 아이디어? 대단히 감사합니다!

  • 답변 # 1

    서블릿은 웹 애플리케이션 시작시 한 번만 작성되며 모든 요청간에 공유됩니다. 정적이든 아니든 모든 클래스/인스턴스 변수는 모든 요청/세션간에 공유됩니다. 요청/세션 범위 데이터를 할당하고 싶지 않습니다. 대신 메소드 로컬 변수로 선언/할당하십시오. 예 :

    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.
        }
    }
    
    

    레거시 및더 이상 사용되지 않음 SingleThreadModel 가 있습니다  모든 요청 중에 서블릿이 강제로 작성하도록 구현할 수있는 인터페이스. 그러나 이것은 나쁜 디자인이며 불필요하게 비쌉니다. 이것이 더 이상 사용되지 않는 이유이기도합니다.

    참조 :

    서블릿 인스턴스 및 멀티 스레딩

    서블릿은 어떻게 작동합니까?

  • 답변 # 2

    static  모든 인스턴스가 동일한 값에 액세스 함을 의미합니다.
    따라서 서블릿에 연결된 모든 사용자는 동일한 값에 액세스합니다. 2 명 이상의 사용자가 서로 연결되어 있으면 jobId가 잘못되었을 수 있습니다.

    각 연결마다 자신의 가치를 얻어 다른 곳에 저장해야합니다.

    <시간>

    자원 :

    서블릿의 정적 변수-언제 사용할 수 있습니까?

    동일한 주제 :

    서블릿과 웹 서비스 사이에 정적 객체 공유하기

  • 답변 # 3

    정적 변수는 공유됩니다. 정적 변수는 하나의 인스턴스에 속하지 않으며 클래스의 모든 인스턴스에서 액세스 할 수 있습니다. 생성자를 사용하는 경우 생성자에서 하나의 객체 (클래스의 한 인스턴스)를 만드는 데 사용됩니다. 생성자에서 정적 변수를 설정하는 것은 생성하는 객체의 범위를 벗어난 것이기 때문에 일반적으로 의미가 없습니다. .

    작동하는 것에 관해서는 HttpSession에 jobId를 넣을 수 있고 각 사용자는 자신의 사본을 가질 수 있습니다.

  • 답변 # 4

    서블릿의 인스턴스화 정책은 서블릿 스펙에 정의되어 있지 않습니다 ( 내가 기억할 수있는 한, 누구든지)하지만 일반적인 동작은 서블릿 구성 당 하나의 인스턴스 만 만드는 것 같습니다. 따라서 귀하의 경우 모든 요청에 ​​동일한 변수가 사용됩니다.

    내가 너라면, jobId를 매개 변수로 Runnable 에 보내는 것을 고려할 것이다 스레드를 실행 중입니다. 예를 들어,이 대신에 :

    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
            }
        }
    }
    
    

    읽기 쉽고 동시성 문제가 없음-순수한 승리.

  • 이전 session - Facebook 앱은 모든 브라우저에서 작동하지만 IE8에서는 작동하지 않습니다
  • 다음 python - xaxis 끝에 xlabel을 설정하는 방법