我一直在尝试在我的Java Servlet中执行延迟1秒的代码。我需要检查跟踪打开或关闭的条件。如果关闭,则转到其他位置并关闭调度程序。代码如下。

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // TODO Auto-generated method stub

    Map m=request.getParameterMap();
    Set s = m.entrySet();
    Iterator it = s.iterator();
    int index=0;

        while(it.hasNext()){

            Map.Entry<String,String[]> entry = (Map.Entry<String,String[]>)it.next();

            String key             = entry.getKey();
            String[] value         = entry.getValue();

            System.out.println("Value is "+value[0].toString());
                     switch(key)
                     {
                     case "RegId":
                         RegId=value[0].toString();
                         break;
                     case "isTrackingRequested":
                         isTrackingRequested=Boolean.valueOf(value[0]);
                         break;
         }
     }
    boolean isTrackingRequestednew=isTrackingRequested;
    ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();

        ses.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {

                // code to run
                if(isTrackingRequestednew){
                    try {
                        System.out.println("===========================================================================");
                        System.out.println("new track status is "+isTrackingRequestednew);
                        System.out.println("===========================================================================");

                        }catch(Exception e)
                        {

                        }
                     }
                else
                {
                    ses.shutdown();

                }
            }
        }, 0, 1, TimeUnit.SECONDS);
}


现在,为了停止跟踪,我的应用程序将isTrackingRequestednew作为“ false”发送,现在此值根本没有更改。我不知道为什么会这样。请帮我。

最佳答案

此代码无法编译,您无法访问内部类内部的局部(而非最终)变量。
每次发布请求时,您都可以创建新的ExecutorService,而不是为每个会话或跟踪实体创建一次。我不知道该线程的作用是什么,所以我将保留您怪异的代码样式

private static class TrackingInfo {
    final private AtomicBoolean status;
    final private ScheduledExecutorService ses;

    TrackingInfo(boolean flagStatus) {
        this.status = new AtomicBoolean(flagStatus);
        this.ses = Executors.newSingleThreadScheduledExecutor();
        ses.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {

                // code to run
                if (status.get()) {
                    try {
                        System.out.println("===========================================================================");
                        System.out.println("new track status is " + status.get());
                        System.out.println("===========================================================================");

                    } catch (Exception e) {

                }
                } else {
                    ses.shutdown();
                }
            }
        }, 0, 1, TimeUnit.SECONDS);
    }

    public void setStatus(boolean status) {
        this.status.set(status);
    }
}


使用request.getSession().getAttribute(...) / setAttribute()将该TrackingInfo和worker保留在其中,并通过TrackingInfo.setStatus(newStatus)实例将标志更改传递给worker,或者您可以在控制器类中包含一些Map变量(而不是方法局部变量)并存储跟踪ID和TrackingInfo与之相关。
恕我直言,如果您真正终止跟踪线程就像在已发布的代码中一样简单

else {
    ses.shutdown();
}


您根本不需要TrackingInfo。只需存储(如上所述,在会话或高速缓存中)对调度程序的引用,然后您在isTrackingRequestednew方法中收到带有错误值的doPost,就可以获取此调度程序并像这样关闭它

if (!isTrackingRequestednew) {
    ScheduledExecutorService scheduler = (ScheduledExecutorService) request.getSession().getAttribute("trackingScheduler");
    if (scheduler != null) {
        scheduler.shutdown();
    }
}


相反,您可以使用一些跟踪ID作为标识符,并随每个请求发送。
请注意,您还必须清理由于某些网络错误或其他原因未正确关闭的旧调度程序。

09-28 05:00