2013-02-15 44 views
17

Tôi có một ScheduledThreadPoolExecutor mà tôi lên lịch một nhiệm vụ để chạy với tốc độ cố định. Tôi muốn nhiệm vụ được chạy với độ trễ được chỉ định cho tối đa 10 lần cho đến khi nó "thành công". Sau đó, tôi sẽ không muốn nhiệm vụ được thử lại. Vì vậy, về cơ bản tôi sẽ cần phải ngừng chạy tác vụ theo lịch trình khi tôi muốn nó được dừng lại, nhưng không tắt ScheduledThreadPoolExecutor. Bất kỳ ý tưởng làm thế nào tôi muốn làm điều đó?Làm thế nào để dừng một tác vụ trong ScheduledThreadPoolExecutor khi tôi nghĩ rằng nó đã hoàn thành

Dưới đây là một số giả -

public class ScheduledThreadPoolExecutorTest 
{ 
    public static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(15); // no multiple instances, just one to serve all requests 

    class MyTask implements Runnable 
    { 
    private int MAX_ATTEMPTS = 10; 
    public void run() 
    { 
     if(++attempt <= MAX_ATTEMPTS) 
     { 
     doX(); 
     if(doXSucceeded) 
     { 
      //stop retrying the task anymore 
     } 
     } 
     else 
     { 
     //couldn't succeed in MAX attempts, don't bother retrying anymore! 
     } 
    } 
    } 

    public void main(String[] args) 
    { 
    executor.scheduleAtFixedRate(new ScheduledThreadPoolExecutorTest().new MyTask(), 0, 5, TimeUnit.SECONDS); 
    } 
} 

Trả lời

28

chạy thử nghiệm này, nó in 1 2 3 4 5 và dừng

public class ScheduledThreadPoolExecutorTest { 
    static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(15); // no 
    static ScheduledFuture<?> t; 

    static class MyTask implements Runnable { 
     private int attempt = 1; 

     public void run() { 
      System.out.print(attempt + " "); 
      if (++attempt > 5) { 
       t.cancel(false); 
      } 
     } 
    } 

    public static void main(String[] args) { 
     t = executor.scheduleAtFixedRate(new MyTask(), 0, 1, TimeUnit.SECONDS); 
    } 
} 
+0

Lời cảm ơn hoàn hảo! Tôi đã biết về lịch biểu nhưng tôi đã cố gắng sử dụng cách này: t = executor.scheduleAtFixedRate (MyTask mới(), 0, 1, TimeUnit.SECONDS); t.cancel (true); sẽ không bao giờ hoạt động vì những lý do rõ ràng. Việc hủy tác vụ bên trong việc thực hiện tác vụ có vẻ đúng. – mystarrocks

+0

Cảm ơn. Điều này đã giúp. Thú vị để lưu ý rằng ví dụ này không bao giờ thoát. Tôi nghĩ rằng bạn cần tắt máy thi hành – Kirby

+0

Hoặc đúng hơn là bạn cần 't.get()' và một trình tắt máy thi hành bên trong khối catch của CancellationException – Kirby

5

Nicely hủy bên ngoài của thread:

public class ScheduleTest { 

    @Test 
    public void testCancel() throws Exception { 
     final ScheduledThreadPoolExecutor EXECUTOR = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(2); 
     ScheduledFuture f1 = EXECUTOR.scheduleAtFixedRate(new Runnable() { 
      @Override 
      public void run() { 
       System.out.println("Im alive 1"); 
      } 
     }, 0, 1, TimeUnit.SECONDS); 
     ScheduledFuture f2 = EXECUTOR.scheduleAtFixedRate(new Runnable() { 
      @Override 
      public void run() { 
       System.out.println("Im alive 2"); 
      } 
     }, 0, 2, TimeUnit.SECONDS); 

     Thread.sleep(10000); 
     f1.cancel(true); 
     System.out.println("f1 cancel"); 
     Thread.sleep(10000); 
     f2.cancel(false); 
     System.out.println("f2 cancel"); 
     Thread.sleep(10000); 
    } 
} 

Đôi khi sợi không thể bị hủy, việc này thường được giải quyết qua volatile boolean isCancelled;

+1

Ví dụ điển hình tìm kiếm này từ một thời gian phải đối mặt với rất nhiều vấn đề vì điều này .... Cảm ơn :) – Luffy

2

CountDownLatch là phương pháp thay thế. Khi sợi hoàn tất, hãy gọi countDown() trên chốt. Các chủ đề gọi điện thoại gọi latch.await() cho đến khi tất cả các chủ đề hoàn thành. Tại thời điểm đó, hãy gọi ExecutorService.shutdownNow() để chủ đề chính của bạn không biến thành zombie.

import java.util.concurrent.CountDownLatch; 
import java.util.concurrent.Executors; 
import java.util.concurrent.ScheduledExecutorService; 
import java.util.concurrent.TimeUnit; 

public class ScheduledThreadPoolExecutorTest { 

    static int i = 0; 

    public static void main(String[] args) throws Exception { 
    final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); 
    final CountDownLatch latch = new CountDownLatch(1); 
    executor.scheduleAtFixedRate(() -> { 
     System.out.println(++i); 
     if (i > 4) { 
      latch.countDown(); 
     } 
    }, 0, 100, TimeUnit.MILLISECONDS); 
    latch.await(); 
    executor.shutdownNow(); 
    } 
}