简体   繁体   中英

ScheduledExecutorService does not show the change in variable

I have been trying to execute a code with the delay of 1 second in my java servlet. I need to check the condition if the tracking is on or off. If it is off then it goes to else and shuts the scheduler. The code is as under.

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

Now in order to stop the tracking my application send the isTrackingRequestednew as "false", now this value is not getting changed at all. I dont know why is that happening. Please help me.

This code would not compile, you can't access local (not final) variable inside inner class.
Every time on post request you create new ExecutorService, instead of creating it once per session or tracking entity. I don't know what is the purpose of this thread, so I would save your weird code style

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

use either request.getSession().getAttribute(...) / setAttribute() to hold this TrackingInfo and worker inside it and pass flag changes to worker by TrackingInfo.setStatus(newStatus) instance, or you can have some Map variable in your controller class (not method local variable) and store tracking id and TrackingInfo associated with it.
Imho, if your real terminating of tracking thread is as simple as it is in posted code

else {
    ses.shutdown();
}

you don't need TrackingInfo at all. Simply store (in session or cache as it is described above) reference to the scheduler and than you receive isTrackingRequestednew with false value in your doPost method, get this scheduler and shutdown it like this

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

Instead "trackingScheduler" you can use some tracking id as identifier and send it with every request.
Note that you also have to cleanup old schedulers which were not shutdowned properly due some network errors or whatever.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM