2016-06-21 83 views
0

我有一个具有固定延迟的任务,并且想要在队列ScheduledThreadPoolExecutor中只有一个任务。我的想法是使用getQueue().isEmpty()来检查队列中是否只有一个任务。ScheduledThreadPoolExecutor任务从队列中删除

我知道任务一直保持在队列中,直到固定延迟。我需要确切地知道何时从队列中删除任务。我假定当任务开始执行runnable命令时它被删除。但是我找不到任何说明如此精确的规范。

这里是我想象中的代码:

if (task.getQueue().isEmpty()){ 
     task.schedule(new Runnable() { 
      @Override 
      public void run(){ 
       // do my awesome stuff 
      } 
     }, FIXED_DELAY, TimeUnit.MILLISECONDS); 
    } 

所以这种方式只有一个任务可在队列调度。

+0

你能详细说明你的用例吗?你想达到什么目的?为什么?初始任务开始执行后,你是否想安排另一个任务? – Niels

+0

任务不会自动从工作队列中移除 >直到延迟消失 –

+0

您准备实现什么功能?我闻到一个X/Y-问题。 – Fildor

回答

1

考虑以下几点:

publicinterface ConflictingRunnable extends Runnable { 
    boolean hasConflicts(Runnable other); 
} 

而且

public class ConflictAwareScheduledThreadPoolExecutor { 

    private final Map<Runnable, ScheduledFuture> scheduledRunnables = new HashMap<>(); 

    private final ScheduledThreadPoolExecutor executor; 

    public ConflictAwareScheduledThreadPoolExecutor(final ScheduledThreadPoolExecutor executor) { 
     this.executor = executor; 
    } 

    public ScheduledFuture<?> schedule(Runnable command, 
             long delay, 
             TimeUnit unit) { 
     if (command instanceof ConflictingRunnable) { 
      final ConflictingRunnable conflictingRunnable = (ConflictingRunnable) command; 
      for (final Iterator<Runnable> itt = scheduledRunnables.keySet().iterator(); itt.hasNext();) { 
       final Runnable scheduledRunnable = itt.next(); 
       final ScheduledFuture<?> scheduledFuture = scheduledRunnables.get(scheduledRunnable); 
       if (scheduledFuture.isDone()) { 
        itt.remove(); 
       } else if (conflictingRunnable.hasConflicts(scheduledRunnable)) { 
        return null; 
       } 
      } 
     } 
     final ScheduledFuture<?> t = this.executor.schedule(command, delay, unit); 
     scheduledRunnables.put(command, t); 
     return t; 
    } 
} 

当你运行:

public class ScheduledTest { 

    public static void main(String[] args) throws InterruptedException { 
     final ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(1); 
     final ConflictAwareScheduledThreadPoolExecutor conflictAwareScheduler = new ConflictAwareScheduledThreadPoolExecutor(scheduler); 

     for (int i = 0; i < 100; i++) { 
      conflictAwareScheduler.schedule(new MyTask(i), 100, TimeUnit.MILLISECONDS); 
      Thread.sleep(10); 
     } 

     scheduler.shutdown(); 
    } 

    private static class MyTask implements ConflictingRunnable { 

     private final int i; 

     public MyTask(final int i) { 
      this.i = i; 
     } 


     @Override 
     public boolean hasConflicts(Runnable other) { 
      return other instanceof MyTask; 
     } 

     @Override 
     public void run() { 
      System.out.println(">>> " + i); 
     } 
    } 
} 

你会得到这样的:

>>> 0 
>>> 11 
>>> 21 
>>> 31 
>>> 42 
>>> 53 
>>> 64 
>>> 75 
>>> 86 
>>> 97 

ConflictAwareScheduledThreadPoolExecutor检查是否与已调度/正在运行的任务发生冲突。如果检测到与另一个计划/正在运行的任务发生冲突,则不会计划其他任务。