Timer & TimerTask เทียบกับ Thread + sleep ใน Java


102

ฉันพบคำถามคล้าย ๆ กันที่ถามที่นี่ แต่ไม่มีคำตอบสำหรับความพึงพอใจของฉัน ดังนั้นจึงเปลี่ยนคำถามอีกครั้ง -

ฉันมีงานที่ต้องทำเป็นระยะ (พูดช่วงเวลา 1 นาที) อะไรคือข้อดีของการใช้ Timertask & Timer เพื่อทำสิ่งนี้ซึ่งต่างจากการสร้างเธรดใหม่ที่มีการวนซ้ำแบบไม่มีที่สิ้นสุดพร้อมกับโหมดสลีป

ข้อมูลโค้ดโดยใช้ timertask-

TimerTask uploadCheckerTimerTask = new TimerTask(){

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

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

ข้อมูลโค้ดโดยใช้เธรดและสลีป -

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

ฉันไม่ต้องกังวลจริงๆถ้าฉันพลาดบางรอบหากการดำเนินการของตรรกะใช้เวลามากกว่าช่วงเวลา

แสดงความคิดเห็นได้ที่นี้ ..

อัปเดต:
เมื่อเร็ว ๆ นี้ฉันพบความแตกต่างอีกอย่างระหว่างการใช้ Timer กับ Thread.sleep () สมมติว่าเวลาของระบบปัจจุบันคือ 11.00 น. หากเราย้อนกลับเวลาของระบบเป็น 10:00 น. ด้วยเหตุผลบางประการตัวจับเวลาจะหยุดดำเนินการงานจนกว่าจะถึง 11:00 น. ในขณะที่เมธอด Thread.sleep () จะดำเนินการงานต่อไปโดยไม่มีอุปสรรค สิ่งนี้สามารถเป็นผู้ตัดสินใจหลักในการตัดสินใจว่าจะใช้อะไรระหว่างสองสิ่งนี้


21
จุดสั่งซื้อ: Timer และ TimerTask ล้าสมัยและถูกแทนที่ด้วย ExecutorService อย่างมีประสิทธิภาพแม้ว่าจุดของคุณจะยังคงอยู่
skaffman

ขอบคุณสำหรับเคล็ดลับฉันตัดสินใจใช้ ExecutorService :)
Keshav

ขอบคุณทุกคนสำหรับคำตอบทำให้ฉันเข้าใจมากขึ้นอย่างแน่นอน!
Keshav

6
ตัวจับเวลาไม่ล้าสมัยและเป็นที่ต้องการเมื่อต้องการเพียงเธรดเดียว ( java.sun.com/javase/6/docs/api/java/util/Timer.html )
จัสติน

2
Timer และ TimerTask ยังคงมีประโยชน์ในสภาพแวดล้อม JME ที่ไม่มี ExecutorService (เนื่องจากใช้ JME Java 1.3 ... )
スーパーファミコン

คำตอบ:


67

ข้อดีของ TimerTask คือแสดงความตั้งใจของคุณได้ดีกว่ามาก (เช่นการอ่านโค้ด) และมีการใช้งานคุณสมบัติยกเลิก () อยู่แล้ว

โปรดทราบว่าสามารถเขียนในรูปแบบที่สั้นกว่าและตัวอย่างของคุณเอง:

Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(
    new TimerTask() {
      public void run() { NewUploadServer.getInstance().checkAndUploadFiles(); }
    }, 0, 60 * 1000);

ถ้าใช้ตัวจับเวลาสำหรับทุกวันใน 2 เวลาเฉพาะ 21.00 น. และ 9.00 น. ... จะให้ค่าอย่างไร ตามโค้ดด้านบน ... @Zed?
gumuruh

12

Timer / TimerTask ยังคำนึงถึงเวลาดำเนินการของงานของคุณด้วยดังนั้นมันจะแม่นยำกว่าเล็กน้อย และจัดการกับปัญหามัลติเธรดได้ดีขึ้น (เช่นหลีกเลี่ยงการหยุดชะงักเป็นต้น) และแน่นอนว่าโดยปกติแล้วการใช้รหัสมาตรฐานที่ผ่านการทดสอบมาเป็นอย่างดีแทนที่จะใช้โซลูชันแบบโฮมเมด


5

ฉันไม่รู้ว่าทำไม แต่โปรแกรมที่ฉันเขียนใช้ตัวจับเวลาและขนาดฮีปก็เพิ่มขึ้นอย่างต่อเนื่องเมื่อฉันเปลี่ยนเป็นเธรด / ปัญหาการนอนหลับได้รับการแก้ไขแล้ว


9
ตัวจับเวลาสร้างคิวของงานที่อัปเดตอย่างต่อเนื่อง เมื่อตั้งเวลาเสร็จแล้วขยะอาจไม่ถูกเก็บในทันที ดังนั้นการสร้างตัวจับเวลาเพิ่มเติมจะเพิ่มวัตถุเข้าไปในฮีปมากขึ้นเท่านั้น Thread.sleep () จะหยุดเธรดชั่วคราวเท่านั้นดังนั้นค่าใช้จ่ายของหน่วยความจำจะต่ำมาก
Darryl Gerrow

4

หากเธรดของคุณได้รับข้อยกเว้นและถูกฆ่านั่นคือปัญหา แต่ TimerTask จะดูแลมัน มันจะทำงานโดยไม่คำนึงถึงความล้มเหลวในการรันก่อนหน้านี้


4

จากTimer เอกสารประกอบ :

Java 5.0 แนะนำแพ็คเกจ java.util.concurrent และหนึ่งในยูทิลิตี้พร้อมกันในนั้นคือ ScheduledThreadPoolExecutor ซึ่งเป็นเธรดพูลสำหรับการรันงานซ้ำ ๆ ในอัตราหรือความล่าช้าที่กำหนด มันเป็นการทดแทนที่หลากหลายมากขึ้นสำหรับการรวม Timer / TimerTask เนื่องจากอนุญาตให้มีเธรดบริการหลายชุดยอมรับหน่วยเวลาที่หลากหลายและไม่ต้องใช้ TimerTask ย่อย (เพียงแค่ใช้ Runnable) การกำหนดค่า ScheduledThreadPoolExecutor ด้วยเธรดเดียวทำให้เทียบเท่ากับ Timer

ดังนั้นScheduledThreadExecutorแทนที่จะเป็นTimer:

  • Timerใช้เธรดพื้นหลังเดียวที่ใช้เพื่อดำเนินการงานตัวจับเวลาทั้งหมดตามลำดับ ดังนั้นงานควรเสร็จสิ้นอย่างรวดเร็วมิฉะนั้นจะทำให้การดำเนินการตามมาล่าช้า แต่ในกรณีที่ScheduledThreadPoolExecutorเราสามารถกำหนดค่าเธรดจำนวนเท่าใดก็ได้และยังสามารถควบคุมได้ทั้งหมดโดยให้ThreadFactoryและยังสามารถควบคุมเต็มรูปแบบโดยการให้
  • Timerอาจมีความไวต่อนาฬิการะบบเนื่องจากใช้Object.wait(long)วิธีการ แต่ScheduledThreadPoolExecutorไม่ใช่
  • ข้อยกเว้นรันไทม์ที่โยนใน TimerTask จะฆ่าเธรดนั้น ๆ ดังนั้นจึงทำให้ Timer ตายโดยที่เราสามารถจัดการได้ใน ScheduledThreadPoolExecutorเพื่อไม่ให้งานอื่น ๆ ได้รับผลกระทบ
  • Timerมีcancelวิธีการยุติการจับเวลาและทิ้งงานที่กำหนดไว้อย่างไรก็ตามจะไม่รบกวนการทำงานที่กำลังดำเนินการอยู่และปล่อยให้มันเสร็จสิ้น แต่ถ้าไทม์เมอร์รันเป็นเดมอนเธรดไม่ว่าเราจะยกเลิกหรือไม่มันจะสิ้นสุดทันทีที่เธรดผู้ใช้ทั้งหมดทำงานเสร็จสิ้น

ตัวจับเวลากับเธรดการนอนหลับ

Timer ใช้ประโยชน์ได้Object.waitและแตกต่างจากThread.sleep

  1. waitเธรดกำลังรอ ( ) สามารถแจ้งเตือน (โดยใช้notify) โดยเธรดอื่น แต่เธรดหนึ่งไม่สามารถถูกหยุดทำงานได้จะถูกขัดจังหวะเท่านั้น
  2. การรอ (และแจ้งเตือน) จะต้องเกิดขึ้นในบล็อกที่ซิงโครไนซ์บนวัตถุมอนิเตอร์ในขณะที่โหมดสลีปไม่ทำงาน
  3. ขณะนอนหลับไม่ได้คลายล็อกการรอจะคลายล็อกสำหรับวัตถุที่เรียกใช้

ข้อมูลที่มีประโยชน์มากการใช้ Thread.sleep ในวงวนไม่สิ้นสุดอาจทำให้เกิดการใช้งาน CPU สูงในเวลาที่ล่าช้า
Amir Fo

3

มีข้อโต้แย้งที่สำคัญอย่างหนึ่งในการจัดการงานนี้โดยใช้เธรดและsleepวิธีการของJava คุณกำลังใช้while(true)เพื่ออยู่ในลูปไปเรื่อย ๆ และจำศีลเธรดโดยการเข้าสู่โหมดสลีป จะเป็นอย่างไรหากNewUploadServer.getInstance().checkAndUploadFiles();ต้องใช้ทรัพยากรที่ซิงโครไนซ์ เธรดอื่น ๆ จะไม่สามารถเข้าถึงแหล่งข้อมูลเหล่านี้ความอดอยากอาจเกิดขึ้นซึ่งอาจทำให้แอปพลิเคชันทั้งหมดของคุณช้าลง ข้อผิดพลาดประเภทนี้ยากที่จะวินิจฉัยและเป็นความคิดที่ดีที่จะป้องกันไม่ให้มีอยู่

aproach อื่น ๆ ทริกเกอร์การเรียกใช้รหัสที่สำคัญสำหรับคุณกล่าวคือNewUploadServer.getInstance().checkAndUploadFiles();โดยการเรียกใช้run()เมธอดของคุณTimerTaskในขณะที่ปล่อยให้เธรดอื่นใช้ทรัพยากรในขณะเดียวกัน


16
ฉันไม่เข้าใจข้อโต้แย้งนี้ ทั้งสองตัวเลือกเปิดใช้วิธีการเดียวกันจากเธรดตัวเลือกทั้งสองกำลังนอนหลับอยู่ในเธรดในขณะที่รอดำเนินการ จะไม่มีความแตกต่างระหว่างความอดอยากระหว่างสองทางเลือก
satur9nine

2

ฉันคิดว่าฉันเข้าใจปัญหาของคุณฉันเห็นบางอย่างที่คล้ายกันมาก ฉันมีตัวจับเวลาที่เกิดซ้ำบางตัวทุก ๆ 30 นาทีและบางตัวทุกสองสามวัน จากสิ่งที่ฉันอ่านและความคิดเห็นที่ฉันเห็นดูเหมือนว่าการรวบรวมขยะจะไม่มีวันทำงานเพราะงานทั้งหมดจะไม่เสร็จสมบูรณ์ ฉันคิดว่าการเก็บขยะจะทำงานเมื่อตัวจับเวลาอยู่ในโหมดสลีป แต่ฉันไม่เห็นและตามเอกสารนั้นไม่เห็น

ฉันคิดว่าการตั้งกระทู้ใหม่เสร็จสมบูรณ์และอนุญาตให้เก็บขยะได้

ใครบางคนโปรดพิสูจน์ว่าฉันผิดการเขียนสิ่งที่ฉันได้รับมาใหม่จะเป็นความเจ็บปวด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.