2016-06-21 81 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檢查是否與已調度/正在運行的任務發生衝突。如果檢測到與另一個計劃/正在運行的任務發生衝突,則不會計劃其他任務。