【问题标题】:ScheduledExecutorService does not show the change in variableScheduledExecutorService 不显示变量的变化
【发布时间】:2015-12-23 09:45:51
【问题描述】:

我一直在尝试在我的 java servlet 中执行延迟 1 秒的代码。如果跟踪打开或关闭,我需要检查条件。如果它关闭,那么它会转到 else 并关闭调度程序。代码如下。

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”,现在这个值根本没有改变。我不知道为什么会这样。请帮帮我。

【问题讨论】:

  • 该标志是该方法的本地标志,因此,它会随着每个请求而改变。另外,我认为调度/停止任务的逻辑应该在一个单独的类中而不是在 servlet 中,并且应该由一个实例变量控制。
  • @Darshan Mehta 如果我创建实例变量并将任务委托给某个类方法,它将为每个请求形成新对象(一个用于“打开”,另一个用于“关闭”)。我需要为同一用户处理关闭功能,如果我每次都创建对象并委托,这是不可能的。我希望你明白我的意思。
  • @DarshanMehta 我也有同样的想法,但变量的值没有改变。
  • 你能分享完整的代码吗?我们在哪里声明了“isTrackingRequested”标志?
  • @DarshanMehta isTrackingRequested 的值来自移动应用程序并且非常准确。标志 isTrackingRequested 显示更改,但变量 isTrackingRequestednew 没有。

标签: java servlets scheduledexecutorservice


【解决方案1】:

此代码无法编译,您无法访问内部类中的本地(非最终)变量。
每次发布请求时,您都会创建新的 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。只需存储(如上所述在会话或缓存中)对调度程序的引用,然后在您的 doPost 方法中收到带有 false 值的 isTrackingRequestednew,获取此调度程序并像这样关闭它

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

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

【讨论】:

  • 至于你在这里的建议,我看到你已经创建了一个新类。现在因为它是一个 servlet,如果我需要访问这个类方法,我需要创建一个对象然后访问它。通过这样做,每次我向 servlet 发布任何请求时,我最终都会创建新对象。因此我无法停止调度程序,因为我无权访问前一个对象。
  • 不,正如我在您的 servlet 中所说的 use either request.getSession().getAttribute(...) / setAttribute() to hold this TrackingInfo 和 or you can have some Map。一次创建并多次访问。
猜你喜欢
  • 1970-01-01
  • 2021-07-01
  • 2020-12-15
  • 2021-07-24
  • 2022-11-02
  • 2017-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多