2015-12-16 17 views
13

Tôi muốn trì hoãn làm điều gì đó, dọc theo các dòng thiết lập đồng hồ đếm ngược sẽ "làm một điều" sau một khoảng thời gian nhất định.Làm cách nào để lên lịch một tác vụ để chạy một lần?

Tôi muốn phần còn lại của chương trình của tôi để tiếp tục chạy trong khi tôi chờ đợi, vì vậy tôi đã cố gắng làm của riêng tôi Thread có chứa một sự chậm trễ một phút:

public class Scratch { 
    private static boolean outOfTime = false; 

    public static void main(String[] args) { 
     Thread countdown = new Thread() { 
      @Override 
      public void run() { 
       try { 
        // wait a while 
        System.out.println("Starting one-minute countdown now..."); 
        Thread.sleep(60 * 1000); 

        // do the thing 
        outOfTime = true; 
        System.out.println("Out of time!"); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     }; 
     countdown.start(); 

     while (!outOfTime) { 
      try { 
       Thread.sleep(1000); 
       System.out.println("do other stuff here"); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 


Trong khi điều này làm việc, hơn-hay- ít hơn, nó có vẻ như có một cách tốt hơn để làm điều này.

Sau khi một số tìm kiếm, tôi tìm thấy một loạt các câu hỏi như thế này nhưng họ không thực sự giải quyết những gì tôi đang cố gắng để làm:

Tôi không cần bất cứ điều gì phức tạp này ted; Tôi chỉ muốn làm một điều duy nhất sau một khoảng thời gian nhất định trong khi để phần còn lại của chương trình vẫn chạy.

Tôi nên làm thế nào để lên kế hoạch cho tác vụ một lần để "làm một điều"?

Trả lời

16

Trong khi java.util.Timer được sử dụng là cách tốt để lên lịch các tác vụ trong tương lai, bây giờ thích hợp hơn là để sử dụng các lớp học trong gói java.util.concurrent.

Có một ScheduledExecutorService được thiết kế đặc biệt để chạy lệnh sau khi trì hoãn (hoặc thực thi chúng theo định kỳ, nhưng điều đó không liên quan đến câu hỏi này).

Nó có một phương pháp schedule(Runnable, long, TimeUnit) rằng

Tạo và thực thi một hành động one-shot mà trở nên kích hoạt sau độ trễ nhất định.


Sử dụng một ScheduledExecutorService bạn có thể viết lại chương trình của bạn như thế này:

import java.util.concurrent.*; 

public class Scratch { 
    private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); 
    public static void main(String[] args) { 
     System.out.println("Starting one-minute countdown now..."); 
     ScheduledFuture<?> countdown = scheduler.schedule(new Runnable() { 
      @Override 
      public void run() { 
       // do the thing 
       System.out.println("Out of time!"); 
      }}, 1, TimeUnit.MINUTES); 

     while (!countdown.isDone()) { 
      try { 
       Thread.sleep(1000); 
       System.out.println("do other stuff here"); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
     scheduler.shutdown(); 
    } 
} 

Một trong những điều tốt đẹp bạn sẽ có được bằng cách làm việc theo cách này là đối tượng ScheduledFuture<?> bạn trở lại từ gọi schedule() .

Điều này cho phép bạn loại bỏ biến số boolean bổ sung và chỉ kiểm tra trực tiếp xem công việc có chạy hay không.

Bạn cũng có thể hủy tác vụ đã lên lịch nếu bạn không muốn chờ đợi nữa bằng cách gọi phương thức cancel() của nó.


Xem Java Timer vs ExecutorService? vì những lý do để tránh sử dụng một Timer ủng hộ của một ExecutorService.

+0

người thực thi được lên lịch này sẽ chạy một lần hoặc mỗi phút. Tôi muốn tôi chạy một lần và đi ra. – qualebs

+0

@qualebs Trong ví dụ này, hành động sẽ chỉ chạy một lần. Thời gian được chuyển vào phương thức 'schedule()' là độ trễ trước khi hành động được chạy. – azurefrog

Các vấn đề liên quan