Timer & TimerTask versus Thread + sleep di Java

102

Saya menemukan pertanyaan serupa ditanyakan di sini tetapi tidak ada jawaban yang memuaskan saya. Jadi ulangi pertanyaannya lagi-

Saya memiliki tugas yang perlu dilakukan secara berkala (katakanlah interval 1 menit). Apa keuntungan menggunakan Timertask & Timer untuk melakukan ini dibandingkan membuat utas baru yang memiliki loop tak terbatas dengan tidur?

Potongan kode menggunakan timertask-

TimerTask uploadCheckerTimerTask = new TimerTask(){

 public void run() {
  NewUploadServer.getInstance().checkAndUploadFiles();
 }
};

Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(uploadCheckerTimerTask, 0, 60 * 1000);

Potongan kode menggunakan Thread dan sleep-

Thread t = new Thread(){
 public void run() {
  while(true) {
   NewUploadServer.getInstance().checkAndUploadFiles();
   Thread.sleep(60 * 1000);
  }
 }
};
t.start();

Saya benar-benar tidak perlu khawatir jika saya melewatkan siklus tertentu jika eksekusi logika membutuhkan waktu lebih dari interval waktu.

Tolong komentari ini ..

Pembaruan:
Baru-baru ini saya menemukan perbedaan lain antara menggunakan Timer versus Thread.sleep (). Misalkan waktu sistem saat ini adalah 11:00. Jika kita mengembalikan waktu sistem ke 10:00 karena alasan tertentu, Timer akan BERHENTI menjalankan tugas hingga mencapai jam 11:00, sedangkan metode Thread.sleep () akan terus menjalankan tugas tanpa hambatan. Ini bisa menjadi pembuat keputusan utama dalam memutuskan apa yang akan digunakan di antara keduanya.

Keshav
sumber
21
Point of order: Timer dan TimerTask sudah usang, dan secara efektif telah diganti oleh ExecutorService, meskipun poin Anda masih berlaku.
Skaffman
Terima kasih atas tipnya, saya memutuskan untuk menggunakan ExecutorService :)
Keshav
Terima kasih atas jawabannya, pasti memberi saya lebih banyak pengertian!
Keshav
6
Timer tidak ketinggalan zaman, dan lebih disukai jika hanya diperlukan satu utas. ( java.sun.com/javase/6/docs/api/java/util/Timer.html )
Justin
2
Timer dan TimerTask masih berguna di lingkungan JME di mana ExecutorService tidak ada (karena JME berbasis Java 1.3 ...).
ス ー パ ー フ ァ ミ コ ン

Jawaban:

67

Keuntungan dari TimerTask adalah ia mengekspresikan maksud Anda dengan lebih baik (yaitu keterbacaan kode), dan fitur cancel () sudah diimplementasikan.

Perhatikan bahwa itu bisa ditulis dalam bentuk yang lebih pendek serta contoh Anda sendiri:

Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(
    new TimerTask() {
      public void run() { NewUploadServer.getInstance().checkAndUploadFiles(); }
    }, 0, 60 * 1000);
Zed
sumber
jika timer digunakan untuk Everyday, pada 2 waktu tertentu 9pm dan 9am, ... bagaimana cara memberikan nilainya? pada kode di atas ... @Zed?
gumuruh
12

Timer / TimerTask juga memperhitungkan waktu eksekusi tugas Anda, jadi akan sedikit lebih akurat. Dan itu lebih baik menangani masalah multithreading (seperti menghindari kebuntuan, dll.). Dan tentu saja biasanya lebih baik menggunakan kode standar yang telah teruji dengan baik daripada larutan buatan sendiri.

MartinStettner
sumber
5

Saya tidak tahu mengapa tetapi program yang saya tulis menggunakan Timer dan ukuran tumpukannya terus meningkat, setelah saya mengubahnya menjadi masalah Thread / sleep yang diselesaikan.

Qandeel
sumber
9
Timer membuat antrian tugas yang terus diperbarui. Saat Timer selesai, mungkin sampah tidak segera dikumpulkan. Jadi membuat lebih banyak Timer hanya menambahkan lebih banyak objek ke heap. Thread.sleep () hanya menjeda utas, jadi overhead memori akan sangat rendah.
Darryl Gerrow
4

Jika utas Anda mendapatkan pengecualian dan terbunuh, itu adalah masalah. Tapi TimerTask akan menanganinya. Ini akan berjalan terlepas dari kegagalan dalam proses sebelumnya.

Stack Popper
sumber
4

Dari Timer dokumentasi :

Java 5.0 memperkenalkan paket java.util.concurrent dan salah satu utilitas konkurensi di dalamnya adalah ScheduledThreadPoolExecutor yang merupakan kumpulan thread untuk berulang kali menjalankan tugas pada kecepatan atau penundaan tertentu. Ini secara efektif merupakan pengganti yang lebih fleksibel untuk kombinasi Timer / TimerTask, karena memungkinkan beberapa utas layanan, menerima berbagai unit waktu, dan tidak memerlukan subclass TimerTask (cukup terapkan Runnable). Mengonfigurasi ScheduledThreadPoolExecutor dengan satu utas membuatnya setara dengan Timer.

Jadi Lebih Memilih ScheduledThreadExecutordaripada Timer:

  • Timermenggunakan utas latar belakang tunggal yang digunakan untuk menjalankan semua tugas pengatur waktu, secara berurutan. Jadi tugas harus diselesaikan dengan cepat jika tidak maka akan menunda pelaksanaan tugas selanjutnya. Tetapi jika ScheduledThreadPoolExecutorkita dapat mengkonfigurasi sejumlah utas dan juga dapat memiliki kontrol penuh dengan menyediakan ThreadFactory.
  • Timerbisa peka terhadap jam sistem karena menggunakan Object.wait(long)metode. Tapi ScheduledThreadPoolExecutortidak.
  • Pengecualian waktu proses yang dilemparkan di TimerTask akan mematikan utas tertentu itu, sehingga membuat Timer mati di mana karena kami dapat menanganinya ScheduledThreadPoolExecutorsehingga tugas lain tidak terpengaruh.
  • Timermenyediakan cancelmetode untuk menghentikan pengatur waktu dan membuang semua tugas terjadwal, namun itu tidak mengganggu tugas yang sedang dijalankan dan membiarkannya selesai. Tetapi jika timer berjalan sebagai utas daemon maka apakah kita membatalkannya atau tidak, itu akan dihentikan segera setelah semua utas pengguna selesai dijalankan.

Timer vs Thread.sleep

Timer memanfaatkan Object.waitdan berbeda dariThread.sleep

  1. Sebuah waitthread waiting ( ) dapat diberitahukan (menggunakan notify) oleh thread lain tetapi thread yang sedang tidur tidak dapat, itu hanya dapat diinterupsi.
  2. Tunggu (dan beri tahu) harus terjadi di blok yang disinkronkan pada objek monitor sedangkan sleep tidak.
  3. Saat tidur tidak melepaskan kunci, menunggu akan melepaskan kunci untuk menunggu objek dipanggil.
akhil_mittal
sumber
informasi yang sangat berguna, Ditambah menggunakan Thread.sleep dalam loop tak terbatas dapat menyebabkan penggunaan CPU yang tinggi dalam jumlah waktu tunda yang rendah.
Amir Fo
3

Ada satu argumen penting yang menentang pengelolaan tugas ini menggunakan utas dan sleepmetode Java . Anda menggunakan while(true)untuk tetap berada di loop tanpa batas dan menghibernasi utas dengan mengaktifkan mode tidur. Bagaimana jika NewUploadServer.getInstance().checkAndUploadFiles();membutuhkan beberapa sumber daya yang disinkronkan. Utas lain tidak akan dapat mengakses sumber daya ini, kelaparan mungkin terjadi yang dapat memperlambat seluruh aplikasi Anda. Jenis kesalahan ini sulit untuk didiagnosis dan sebaiknya dicegah keberadaannya.

Pendekatan lain memicu eksekusi kode yang penting bagi Anda, yaitu NewUploadServer.getInstance().checkAndUploadFiles();dengan memanggil run()metode Anda TimerTasksementara membiarkan thread lain menggunakan sumber daya untuk sementara.

Boris Pavlović
sumber
16
Saya tidak mengerti argumen ini. Kedua pilihan meluncurkan metode yang sama dari utas, kedua pilihan tertidur di utas sementara menunggu untuk dieksekusi. Tidak akan ada perbedaan kelaparan antara kedua pilihan tersebut.
satur9nine
2

Saya rasa saya memahami masalah Anda, saya melihat sesuatu yang sangat mirip. Saya memiliki pengatur waktu yang berulang, beberapa setiap 30 menit dan beberapa setiap beberapa hari. Dari yang saya baca dan komentar yang saya lihat, sepertinya pengumpulan sampah tidak akan pernah berjalan karena semua tugas tidak pernah selesai. Saya akan berpikir bahwa pengumpulan sampah akan berjalan ketika pengatur waktu dalam keadaan tidur, tetapi saya tidak melihatnya dan menurut dokumentasi itu tidak.

Saya pikir pemijahan utas baru selesai dan memungkinkan pengumpulan sampah.

Seseorang tolong buktikan saya salah, menulis ulang apa yang saya warisi akan menyebalkan.

Ken
sumber