2009-08-24 15 views
7

Tôi đang sử dụng java.util.Timer để lên lịch một tác vụ định kỳ. Tại một thời điểm, tôi muốn tắt nó và đợi để hoàn thành.Đang đợi Bộ hẹn giờ kết thúc bằng Java

Timer.cancel() sẽ ngăn mọi tác vụ trong tương lai chạy. Làm cách nào để đảm bảo mọi tác vụ hiện không hoạt động (hoặc đợi cho chúng hoạt động?)

Tôi có thể giới thiệu cơ chế đồng bộ bên ngoài, nhưng tôi không thấy cách chúng có thể bao phủ tất cả các trường hợp. Ví dụ, nếu tôi đồng bộ hóa trên một số Màn hình trong tác vụ, tôi vẫn bỏ lỡ trường hợp khi tác vụ mới bắt đầu thực hiện nhưng không lấy màn hình.

Thực tiễn được khuyến nghị để chờ cho đến khi tất cả các tác vụ được thực hiện, bao gồm các tác vụ hiện đang chạy là gì?

Trả lời

18

Bạn nên sử dụng ScheduledExecutorService thay vì Bộ hẹn giờ để lên lịch cho tác vụ định kỳ của mình. ScheduledExecutorService cung cấp một phương thức shutdown() sẽ thực hiện bất kỳ nhiệm vụ đang chờ xử lý nào. Sau đó bạn có thể gọi awaitTermination() để đợi shutdown() kết thúc.

+0

+1. Hoặc, nếu bạn phải sử dụng một 'Timer' vì một lý do nào đó, thì bạn có thể sử dụng một điều kiện (http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/locks/ Condition.html) để đồng bộ hóa hai luồng trên một sự kiện (chẳng hạn như hoàn thành tác vụ theo lịch). –

+2

Vâng, mục 68 trong Java hiệu quả (phiên bản 2) đề xuất ScheduledThreadPoolExecutor như là một sự thay thế linh hoạt hơn cho Bộ hẹn giờ. +1 để đề cập đến điều này, vì thực hành được đề xuất đã được yêu cầu. – Jonik

+0

Vâng, tôi thực sự nên đọc cuốn sách đó. – ripper234

0

Cái gì đó như dưới đây có thể giúp bạn needs-

import java.util.Timer; 
import java.util.TimerTask; 

public class TimerGracefulShutdown { 
    public static void main(String[] args) throws InterruptedException { 
     //This is a synchronization helper class 
     SyncHelper syncHelper = new SyncHelper(); 

     TimerManager myTimerManager = new TimerManager(syncHelper); 

     //Try stopping timer after 5 seconds (it wont stop until the 30 seconds sleep of timertask does not finish) 
     Thread.currentThread().sleep(5000); 
     System.out.println("Going to stop my timer now"); 
     myTimerManager.stopTimer(); 
     System.out.println("Cancelled timer"); 
    } 
} 

class TimerManager { 

    SyncHelper syncHelper; 
    Timer timer; 

    public TimerManager(SyncHelper syncHelper) { 
     this.syncHelper = syncHelper; 
     startTimer(); 
    } 

    private void startTimer() { 
     timer = new Timer(true); 
     TimerTask myTask = new MyTimerTask(syncHelper); 
     timer.scheduleAtFixedRate(myTask, 0, 100000); 
    } 

    public void stopTimer() { 
     try { 
      syncHelper.testAndSetOrReset("acquire"); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 

     //Shutdown the timer here since you know that your timertask is not executing right now. 
     timer.cancel(); 
     try { 
      syncHelper.testAndSetOrReset("release"); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

} 

class MyTimerTask extends TimerTask { 

    private SyncHelper syncHelper; 

    public MyTimerTask(SyncHelper syncHelper) { 
     this.syncHelper = syncHelper; 
    } 

    public void run() { 
     try { 
      syncHelper.testAndSetOrReset("acquire"); 
     } catch (Exception e1) { 
      e1.printStackTrace(); 
     } 

     System.out.println("Over here"); 
     try { 
      Thread.currentThread().sleep(30000); 
     } catch(Exception e) { 

     } 
     System.out.println("Done sleeping"); 

     //Finally release the helper. 
     try { 
      syncHelper.testAndSetOrReset("release"); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

} 

class SyncHelper { 

    private int index = 0; 

    public synchronized void testAndSetOrReset(String command) throws Exception { 

     if("acquire".equals(command)) { 
      if(index == 1) { 
       wait(); 
      } 
      index++; 
     } else if("release".equals(command)) { 
      index--; 
      notifyAll(); 
     } 
    } 
} 
+0

Bạn nên sử dụng 'Thread.sleep (. ..) 'thay vì' Thread.currentThread(). sleep (...) 'bởi vì nó là một phương thức tĩnh; mã của bạn có thể cám dỗ bạn làm 'someOtherThread.sleep (...)' mà không ngủ 'someOtherThread'. – newacct