【问题标题】:java ScheduleExecutorService timeout taskjava ScheduleExecutorService超时任务
【发布时间】:2013-12-15 07:04:21
【问题描述】:

我必须在某个时间间隔安排一些任务,并且必须终止花费超过指定时间的任务。

代码:

public class ExecutorMain {
  public static void main(String[] args) throws InterruptedException, ExecutionException,        TimeoutException {
    ScheduledThreadPoolExecutor scheduledExecutorService = new     ScheduledThreadPoolExecutor(2);
    scheduledExecutorService.scheduleAtFixedRate(new ShortTask(2), 0, 3, TimeUnit.SECONDS);
    scheduledExecutorService.scheduleAtFixedRate(new LongTask(1), 0, 10, TimeUnit.SECONDS);
  }
}

class ShortTask implements Runnable {
  private int id;
  ShortTask(int id) {
    this.id = id;
  }
  public void run() {
    try {
        Thread.sleep(1000);
        System.out.println("Short Task with id "+id+" executed by "+Thread.currentThread().getId());
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
  }
}

class LongTask implements Runnable {
  private int id;
  LongTask(int id) {
    this.id = id;
  }
  public void run() {
    try {
        Thread.sleep(6000);
        System.out.println("Long Task with id "+id+" executed by "+Thread.currentThread().getId());
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
  }
}

在上面的例子中,我想在不干扰其他任务执行的情况下终止耗时超过 5 秒的任务(LongTask)。实现这一目标的最佳方法是什么?

【问题讨论】:

    标签: java scheduledexecutorservice


    【解决方案1】:

    经过深思熟虑和大量搜索,采用以下方法。

    解决方案来自:https://stackoverflow.com/a/808367/3048186

    public class ExecutorMain {
       public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
          ScheduledThreadPoolExecutor scheduledExecutorService = new ScheduledThreadPoolExecutor(2);
          scheduledExecutorService.scheduleAtFixedRate(new ShortTask(1, 5000), 0, 3, TimeUnit.SECONDS);
          scheduledExecutorService.scheduleAtFixedRate(new ShortTask(2, 5000), 0, 3, TimeUnit.SECONDS);
          scheduledExecutorService.scheduleAtFixedRate(new LongTask(1, 5000), 0, 10, TimeUnit.SECONDS);
          scheduledExecutorService.scheduleAtFixedRate(new LongTask(2, 5000), 0, 10, TimeUnit.SECONDS);
       }
    }
    
    class Worker extends Thread {
      private final Process process;
      private Integer exit;
      String id;
      Worker(Process process, String id) {
        this.process = process;
        this.id = id;
      }
      public void run() {
        try {
            exit = process.waitFor();
        } catch (InterruptedException ignore) {
            //NOOP
        }
    }
    
    public Integer getExit() {
        return exit;
      }
    }
    
    class ShortTask implements Runnable {
      private int id;
      private long timeOut;
      ShortTask(int id, long timeOut) {
        this.id = id;
        this.timeOut = timeOut;
      }
      public void run() {
    
        long start = System.currentTimeMillis();
    
        Runtime runtime = Runtime.getRuntime();
        Process process = null;
        try {
            process = runtime.exec("sleep 1s");
        } catch (IOException e) {
            System.out.println("ShortTask IOE");
        }
        Worker worker = new Worker(process, "short task"+id);
        worker.start();
        try {
            worker.join(timeOut);
            long total = System.currentTimeMillis()-start;
            //If time out, exit code would be null
            System.out.println(" Short task id :"+id+" Exit Code : " +worker.getExit()+" thread id "+Thread.currentThread().getId()+" in time "+total);
        } catch(InterruptedException ex) {
            worker.interrupt();
            Thread.currentThread().interrupt();
        } finally {
            if(process != null) {
                process.destroy();
            }
        }
    }
    }
    
    class LongTask implements Runnable {
      private int id;
      private long timeOut;
      LongTask(int id, long timeOut) {
        this.id = id;
        this.timeOut = timeOut;
      }
      public void run() {
    
        long start = System.currentTimeMillis();
    
        Runtime runtime = Runtime.getRuntime();
        Process process = null;
        try {
            process = runtime.exec("sleep 60s");
        } catch (IOException e) {
            System.out.println("LongTask IOE");
        }
        Worker worker = new Worker(process, "long task"+id);
        worker.start();
        try {
            worker.join(timeOut);
            long total = System.currentTimeMillis() - start;
            //If time out, exit code would be null
            System.out.println(" Long Task id :"+id+" Exit Code : " +worker.getExit()+" thread id "+Thread.currentThread().getId()+" in time "+total);
        } catch(InterruptedException ex) {
            worker.interrupt();
            Thread.currentThread().interrupt();
        } finally {
            if(process != null) {
                process.destroy();
            }
        }
      }
    }
    

    【讨论】:

      【解决方案2】:

      使用ScheduledFuture 处理它。试试吧,

      final ScheduledFuture<?> longTaskHandler=
                scheduledExecutorService.scheduleAtFixedRate(new LongTask(1), 
                 0, 10, TimeUnit.SECONDS);
      
      scheduledExecutorService.schedule(new Runnable() {
              public void run() {
                  longTaskHandler.cancel(true);
              // This will cancel your LongTask after 5 sec without effecting ShortTask
              }
          }, 5, TimeUnit.SECONDS);
      

      详情请看这个docs

      【讨论】:

      • 我想到了这一点,但是如果我有多个任务需要超过超时时间来执行,那么我必须将我的线程共享给这个取消任务。如果任务知道它的超时,那么我们就不必安排一个线程来检查超时。
      • @SatishM,这只会影响您的 LongTask,ShortTask 将继续工作。
      • 以上示例执行 2 个任务,但实际上我有多个任务,因此我必须为所有主要任务安排此取消任务(我不知道哪个任务会花费更多时间实际超时)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-17
      • 2017-09-20
      • 2017-08-21
      • 1970-01-01
      • 2019-11-06
      相关资源
      最近更新 更多