Làm cách nào để đặt Timer trong Java?


151

Làm cách nào để đặt Timer, trong 2 phút, để thử kết nối với Cơ sở dữ liệu rồi ném ngoại lệ nếu có bất kỳ vấn đề nào trong kết nối?


1
Coul OP làm rõ nếu họ muốn thực hiện hành động đơn giản trong ít nhất 2 phút hoặc nếu ngoại lệ phải được ném ngay sau hai phút, ngay cả khi một nỗ lực kết nối hiện đang được tiến hành
thecoshman

Câu trả lời:


280

Vì vậy, phần đầu tiên của câu trả lời là làm thế nào để làm những gì đối tượng yêu cầu vì đây là cách ban đầu tôi diễn giải nó và một vài người dường như thấy hữu ích. Câu hỏi đã được làm rõ và tôi đã mở rộng câu trả lời để giải quyết vấn đề đó.

Đặt hẹn giờ

Trước tiên, bạn cần tạo Timer (Tôi đang sử dụng java.utilphiên bản tại đây):

import java.util.Timer;

..

Timer timer = new Timer();

Để chạy tác vụ một khi bạn sẽ làm:

timer.schedule(new TimerTask() {
  @Override
  public void run() {
    // Your database code here
  }
}, 2*60*1000);
// Since Java-8
timer.schedule(() -> /* your database code here */, 2*60*1000);

Để có nhiệm vụ lặp lại sau thời gian bạn sẽ làm:

timer.scheduleAtFixedRate(new TimerTask() {
  @Override
  public void run() {
    // Your database code here
  }
}, 2*60*1000, 2*60*1000);

// Since Java-8
timer.scheduleAtFixedRate(() -> /* your database code here */, 2*60*1000, 2*60*1000);

Làm một thời gian chờ nhiệm vụ

Để thực hiện cụ thể những gì câu hỏi đã làm rõ, đó là cố gắng thực hiện một nhiệm vụ trong một khoảng thời gian nhất định, bạn có thể làm như sau:

ExecutorService service = Executors.newSingleThreadExecutor();

try {
    Runnable r = new Runnable() {
        @Override
        public void run() {
            // Database task
        }
    };

    Future<?> f = service.submit(r);

    f.get(2, TimeUnit.MINUTES);     // attempt the task for two minutes
}
catch (final InterruptedException e) {
    // The thread was interrupted during sleep, wait or join
}
catch (final TimeoutException e) {
    // Took too long!
}
catch (final ExecutionException e) {
    // An exception from within the Runnable task
}
finally {
    service.shutdown();
}

Điều này sẽ thực thi bình thường với các ngoại lệ nếu tác vụ hoàn thành trong vòng 2 phút. Nếu nó chạy lâu hơn thế, TimeoutException sẽ bị ném.

Một vấn đề là mặc dù bạn sẽ nhận được TimeoutException sau hai phút, tác vụ sẽ thực sự tiếp tục chạy , mặc dù có lẽ cơ sở dữ liệu hoặc kết nối mạng cuối cùng sẽ hết thời gian và ném ngoại lệ vào luồng. Nhưng hãy lưu ý rằng nó có thể tiêu thụ tài nguyên cho đến khi điều đó xảy ra.


Ồ tôi đoán bạn đã gặp vấn đề của tôi, tôi phải liên tục cố gắng kết nối với cơ sở dữ liệu đến 2 phút mọi lúc
Ankita

Tôi xin lỗi nhưng yêu cầu của tôi là tôi muốn dành 2 phút để kết nối với cơ sở dữ liệu và sau đó nó sẽ đưa ra một số thông báo lỗi. Giống như tôi muốn đặt giới hạn thời gian để thử kết nối với cơ sở dữ liệu
Ankita

7
ĐỌC HIỂU: Câu trả lời này là sai trái rõ ràng. Nó đặt bộ hẹn giờ chờ 2 phút, rồi chạy truy vấn DB sau 2 phút chậm trễ đó, và sau đó cứ 2 phút lại chạy nó một lần nữa. Những gì nó KHÔNG làm là chạy truy vấn DB ngay lập tức, và sau đó thất bại sau 2 phút, đó là những gì tôi nghĩ rằng câu hỏi được yêu cầu (như đã làm rõ trong nhận xét).
AgilePro

2
@AgilePro Đó là sự thật. Tôi đã không trả lời câu hỏi vì cuối cùng nó đã được nêu và tôi đã cập nhật nó để giải quyết vấn đề đó.
andrewmu

1
@ErnestasGruodis Các API cốt lõi liệt kê hàm tạo là công khai: docs.oracle.com/javase/7/docs/api/java/util/Timer.html#Timer () Bạn có thể có một lớp Timer khác trong đường dẫn lớp của mình - hãy thử java. produc.Timer là lớp học.
andrewmu

25

Dùng cái này

long startTime = System.currentTimeMillis();
long elapsedTime = 0L.

while (elapsedTime < 2*60*1000) {
    //perform db poll/check
    elapsedTime = (new Date()).getTime() - startTime;
}

//Throw your exception

1
hmm ... điều này sẽ hoạt động về mặt kỹ thuật, ngoại trừ nó không bao gồm các trường hợp cạnh, khi bạn hết thời gian NHƯ bạn đang thực hiện một cuộc thăm dò DB, có thể được yêu cầu bởi OP
thecoshman

1
Đây là câu trả lời đúng duy nhất. Nó sẽ chạy trên một luồng duy nhất và sẽ tính thời gian kết thúc mà không bị trôi. Sử dụng TimerTask chính xác là điều sai lầm trong trường hợp này. Tôi ngạc nhiên khi có nhiều ví dụ trên StackOverflow gợi ý điều tương tự như vậy.
AgilePro

1
@thecoshman - việc triển khai bộ đếm thời gian KHÔNG làm gián đoạn hoạt động DB một khi nó đang được tiến hành, cũng không làm điều này. Trong mọi trường hợp, bạn chỉ có thể kiểm soát thời gian bạn bắt đầu hoạt động DB. Có một quan niệm sai lầm phổ biến là bạn cần có "bộ đếm thời gian" để tính thời gian, nhưng bạn thì không. Bạn chỉ cần LÀM GÌ và bằng cách sử dụng thời gian hiện tại, hãy đảm bảo rằng bạn không LÀM NÓ quá lâu.
AgilePro

giả sử bạn phải trả lại kết nối hoặc ném sau CHÍNH XÁC hai phút, điều này sẽ không hoạt động. nếu SAU hai phút cố gắng kết nối bạn vẫn không kết nối được. Trong tình huống kiểm tra kết nối mất hai tuần, việc này sẽ mất nhiều thời gian để đưa ra một ngoại lệ.
thecoshman

14
Đây thực sự là phong cách mã hóa rất tệ, vì vòng lặp while liên tục chạy và kiểm tra các thứ ... xấu cho cpu và xấu cho thời gian sử dụng pin.
Vô hạn

11

Ok, tôi nghĩ rằng tôi hiểu vấn đề của bạn bây giờ. Bạn có thể sử dụng một Tương lai để cố gắng làm một cái gì đó và sau đó hết thời gian sau một chút nếu không có gì xảy ra.

Ví dụ:

FutureTask<Void> task = new FutureTask<Void>(new Callable<Void>() {
  @Override
  public Void call() throws Exception {
    // Do DB stuff
    return null;
  }
});

Executor executor = Executors.newSingleThreadScheduledExecutor();
executor.execute(task);

try {
  task.get(5, TimeUnit.SECONDS);
}
catch(Exception ex) {
  // Handle your exception
}

Ngoại lệ bị ném nhưng chương trình không bị chấm dứt. Xin hãy giúp tôi vượt qua điều này.
Ankita

2
Bạn có thể sử dụng lớp ExecutorService thay vì Executor. Nó có phương thức shutdown () để dừng người thực thi.
Nghi thức

1
Nhân viên điều hành sẽ nuốt những ngoại lệ mà bạn không xử lý cụ thể trong Callable / Runnable của mình. Nếu Runnable / Callable của bạn không bắt và xử lý ngoại lệ đó và nó được cung cấp cho bạn so với việc bạn sở hữu nó, thì bạn cần phải phân lớp lên Lịch trìnhExecutorService và ghi đè afterExecute (đảm bảo gọi super.afterExecute ()). Đối số thứ hai cho afterExecute sẽ có thể được ném ra từ Runnable / Callable
adam

3
    new java.util.Timer().schedule(new TimerTask(){
        @Override
        public void run() {
            System.out.println("Executed...");
           //your code here 
           //1000*5=5000 mlsec. i.e. 5 seconds. u can change accordngly 
        }
    },1000*5,1000*5); 

chỉ cần sao chép mã dịch hại ở trên nó sẽ hoạt động tốt. Tôi đã đưa ra hai lần 'lần đầu tiên' là lần đầu tiên thực thi mã này và lần thứ hai là cho khoảng thời gian.
Mahadev Mane

Thay vào đó, tài liệu dành cho Timer khuyên bạn nên sử dụng khung Executor. docs.oracle.com/javase/10/docs/api/java/util/Timer.html
Karan Khanna

1

[Android] nếu ai đó muốn thực hiện hẹn giờ trên Android bằng java .

bạn cần sử dụng luồng UI như thế này để thực hiện các thao tác.

Timer timer = new Timer();
timer.schedule(new TimerTask() {
           @Override
            public void run() {
                ActivityName.this.runOnUiThread(new Runnable(){
                    @Override
                      public void run() {
                       // do something
                      }        
                });
            }
        }, 2000));
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.