简体   繁体   中英

How do I timeout a method after fixed time in java using concurrency executor future?

Using java concurrent executor, future cancel method not stopping the current task.

I have followed this solution of timeout and stop processing of current task. But it doesn't stop the processing. I am trying this with cron job. Every 30 seconds my cron job gets executed and I am putting 10 seconds timeout. Debug comes in future cancel method, but it is not stopping current task. Thank you.

@Scheduled(cron = "*/30 * * * * *")
    public boolean cronTest()
    {
        System.out.println("Inside cron - start ");
        DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        Date date = new Date();
        System.out.println(dateFormat.format(date));
        System.out.println("Inside cron - end ");

        ExecutorService executor = Executors.newCachedThreadPool();
        Callable<Object> task = new Callable<Object>() {
           public Object call() {
              int i=1;
              while(i<100)
              {
                  System.out.println("i: "+ i++);
                  try {
                      TimeUnit.SECONDS.sleep(1);
                  }
                  catch(Exception e)
                  {
                  }
              }
              return null;
           }
        };
        Future<Object> future = executor.submit(task);
        try {
           Object result = future.get(10, TimeUnit.SECONDS); 
        } catch (Exception e) 
        } finally {
           future.cancel(true);
           return true;
        }
    }

The expected result is cron job runs every 30 seconds and after 10 seconds it should time out and wait for approximately 20 seconds for a cron job to start again. And should not continue the older loop because we have timeout on 10 seconds.

Current result is:

Inside cron - start 
2019/07/25 11:09:00
Inside cron - end 
i: 1
i: 2
i: 3
i: 4 ... upto i: 31
Inside cron - start 
2019/07/25 11:09:30
Inside cron - end 
i: 1
i: 32
i: 2
i: 3
i: 33
...

Expected result is:

Inside cron - start 
2019/07/25 11:09:00
Inside cron - end 
i: 1
i: 2
i: 3
i: 4 ... upto i: 10
Inside cron - start 
2019/07/25 11:09:30
Inside cron - end 
i: 1
i: 2
i: 3 ... upto i:10

The first problem is in this part of code:

catch(Exception e)
{
}

When you invoke future.cancel(true); your thread is being interrupted with Thread.interrupt()
Which means that when a thread is sleeping, it gets awoken and throws InterruptedException which is caught by the catch block and ignored. To fix this problem you have to handle this exception:

catch(InterruptedException e) {
    break; //breaking from the loop
}
catch(Exception e)
{
}

The second problem: Thread.interrupt() may be invoked while the thread is not sleeping. In this case InterruptedException is not thrown. Instead, the interrupted flag of the thread is raised. What you have to do is to check for this flag from time to time, and if it's raised, handle interruption. The basic code for it would look like:

try {
     if (Thread.currentThread().isInterrupted()) {
            break;
     }
     TimeUnit.SECONDS.sleep(1);
}

       ...

// rest of the code

UPDATE:
Here's the full code of Callable :

Callable<Object> task = new Callable<Object>() {
           public Object call() {
              int i=1;
              while(i<100)
              {
                  System.out.println("i: "+ i++);
                  try {
                      if (Thread.currentThread().isInterrupted()) {
                          break; //breaking from the while loop
                      }
                      TimeUnit.SECONDS.sleep(1);
                  } catch(InterruptedException e) {
                      break; //breaking from the while loop
                  } catch(Exception e)
                  {
                  }
              }
              return null;
           }
        };

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