Bagaimana cara mengatur Timer di Java?

151

Bagaimana cara mengatur Timer, katakanlah selama 2 menit, untuk mencoba menghubungkan ke Database kemudian membuang pengecualian jika ada masalah dalam koneksi?

Ankita
sumber
1
Coul OP mengklarifikasi jika mereka ingin mencoba tindakan sederhana untuk setidaknya 2 menit, atau jika pengecualian harus dilemparkan sekarang dua menit kemudian, bahkan jika upaya untuk menghubungkan sedang berlangsung
thecoshman

Jawaban:

280

Jadi, bagian pertama dari jawabannya adalah bagaimana melakukan apa yang diminta subjek karena inilah awalnya saya menafsirkannya dan beberapa orang tampaknya merasa terbantu. Pertanyaan itu sejak diklarifikasi dan saya telah memperluas jawaban untuk mengatasinya.

Mengatur timer

Pertama, Anda perlu membuat Timer (saya menggunakan java.utilversi di sini):

import java.util.Timer;

..

Timer timer = new Timer();

Untuk menjalankan tugas setelah Anda melakukannya:

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);

Untuk mengulangi tugas setelah durasi yang Anda lakukan:

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);

Membuat batas waktu tugas

Untuk secara spesifik melakukan apa yang ditanyakan oleh pertanyaan yang diklarifikasi, yang mencoba melakukan tugas untuk periode waktu tertentu, Anda dapat melakukan hal berikut:

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();
}

Ini akan dieksekusi secara normal dengan pengecualian jika tugas selesai dalam 2 menit. Jika berjalan lebih lama dari itu, TimeoutException akan dibuang.

Salah satu masalah adalah bahwa meskipun Anda akan mendapatkan TimeoutException setelah dua menit, tugas tersebut benar-benar akan terus berjalan , meskipun mungkin koneksi database atau jaringan akhirnya akan habis dan melemparkan pengecualian di utas. Tetapi waspadai itu bisa menghabiskan sumber daya sampai itu terjadi.

andrewmu
sumber
Oh saya kira Anda salah masalah, saya harus berulang kali mencoba untuk terhubung ke database sampai 2 menit setiap kali
Ankita
Saya minta maaf tetapi persyaratan saya adalah saya ingin memberi 2 menit untuk terhubung ke database dan kemudian hanya akan membuang beberapa pesan kesalahan. Sepertinya saya ingin menetapkan batas waktu untuk mencoba terhubung ke database
Ankita
7
PEMBACA WASPADALAH: Jawaban ini sangat salah. Ini mengatur timer untuk menunggu 2 menit, dan kemudian menjalankan permintaan DB setelah penundaan 2 menit itu, dan kemudian menjalankannya lagi dan lagi setiap 2 menit. Apa yang TIDAK dilakukan adalah menjalankan permintaan DB segera, dan kemudian gagal setelah 2 menit itulah yang saya pikir pertanyaannya ditanyakan (seperti yang dijelaskan dalam komentar).
AgilePro
2
@ AgilePro Itu benar. Saya tidak menjawab pertanyaan seperti yang akhirnya dinyatakan dan saya sekarang memperbaruinya untuk mengatasi itu.
andrewmu
1
@ErnestasGruodis API inti mencantumkan konstruktor sebagai publik: docs.oracle.com/javase/7/docs/api/java/util/Timer.html#Timer () Anda mungkin memiliki kelas Timer yang berbeda di classpath Anda - coba java. util.Timer sebagai kelas.
andrewmu
25

Gunakan ini

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

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

//Throw your exception
nimWM
sumber
1
hmm ... ini secara teknis akan berhasil, kecuali itu tidak mencakup kasus tepi, di mana Anda waktu habis SEBAGAI Anda melakukan jajak pendapat DB, yang mungkin diperlukan oleh OP
thecoshman
1
Ini satu-satunya jawaban yang benar. Ini akan berjalan pada satu utas, dan akan menghitung waktu akhir tanpa penyimpangan. Menggunakan TimerTask adalah hal yang salah untuk dilakukan dalam kasus ini. Saya terkejut melihat berapa banyak contoh di StackOverflow menyarankan hal yang salah yang sama.
AgilePro
1
@ thecoshman - implementasi pengatur waktu JANGAN mengganggu operasi DB begitu sedang berlangsung, juga tidak. Bagaimanapun, Anda hanya dapat mengontrol waktu Anda memulai operasi DB. Ada kesalahpahaman umum bahwa Anda memerlukan "timer" untuk mengatur waktu, tetapi Anda tidak. Anda hanya perlu MELAKUKAN sesuatu, dan dengan menggunakan waktu saat ini pastikan Anda tidak MELAKUKANNYA terlalu lama.
AgilePro
katakanlah Anda harus mengembalikan koneksi atau membuang setelah PERSIS dua menit, ini tidak akan berhasil. itu akan terjadi setelah SETELAH dua menit mencoba untuk menghubungkan Anda masih gagal terhubung. Dalam situasi di mana pemeriksaan koneksi membutuhkan waktu dua minggu, ini akan memakan waktu lama untuk membuang pengecualian.
thecoshman
14
Ini sebenarnya gaya pengkodean yang sangat buruk, karena loop sementara terus berjalan dan memeriksa hal-hal ... buruk untuk cpu dan buruk untuk masa pakai baterai.
Infinite
11

Ok, saya pikir saya mengerti masalah Anda sekarang. Anda dapat menggunakan Masa Depan untuk mencoba melakukan sesuatu dan kemudian batas waktu setelah sedikit jika tidak ada yang terjadi.

Misalnya:

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
}
andrewmu
sumber
Pengecualian dilemparkan tetapi program ini tidak dihentikan. Tolong bantu saya melalui ini.
Ankita
2
Anda bisa menggunakan kelas ExecutorService alih-alih Executor. Ini memiliki metode shutdown () untuk menghentikan pelaksana.
Ritus
1
Pelaksana akan menelan pengecualian yang tidak Anda tangani secara khusus di Callable / Runnable Anda. Jika Runnable / Callable Anda tidak menangkap dan menangani pengecualian itu sendiri dan itu disediakan untuk Anda vs Anda yang memilikinya, maka Anda perlu subklas dari ScheduledExecutorService dan menimpa afterExecute (pastikan untuk memanggil super.afterExecute ()). Argumen kedua untuk afterExecute adalah lemparan dari 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); 
Mahadev Mane
sumber
cukup salin kode hama di atas itu akan berfungsi dengan baik. Saya telah memberikan dua kali 'waktu' pertama adalah untuk pertama kalinya untuk mengeksekusi kode ini dan kedua untuk interval waktu.
Mahadev Mane
Dokumentasi untuk Timer merekomendasikan untuk menggunakan kerangka kerja Pelaksana. docs.oracle.com/javase/10/docs/api/java/util/Timer.html
Karan Khanna
1

[Android] jika seseorang ingin menerapkan timer di Android menggunakan java .

Anda perlu menggunakan utas UI seperti ini untuk melakukan operasi.

Timer timer = new Timer();
timer.schedule(new TimerTask() {
           @Override
            public void run() {
                ActivityName.this.runOnUiThread(new Runnable(){
                    @Override
                      public void run() {
                       // do something
                      }        
                });
            }
        }, 2000));
Abhishek Garg
sumber