ในการพัฒนาเรามักจะต้องดำเนินการเป็นระยะเช่นการดำเนินการบางอย่างทุกสองสามนาที ในเวลานี้เราต้องตั้งค่าตัวจับเวลา วิธีที่สะดวกและมีประสิทธิภาพที่สุดในการใช้งานใน Java คือการใช้คลาสเครื่องมือ java.util.timer จากนั้นกำหนดเวลางาน java.util.timertask
ตัวจับเวลาเป็นเครื่องมือที่ใช้เพื่อจัดเรียงงานที่จะดำเนินการในเธรดพื้นหลังในภายหลัง งานสามารถดำเนินการได้หนึ่งครั้งหรือสามารถดำเนินการซ้ำ ๆ ได้ จริงๆแล้วมันเป็นเธรดที่กำหนดเวลา timertasks ที่เป็นเจ้าของโดยการกำหนดเวลาเวลา
Timertask เป็นคลาสนามธรรมที่มีคลาสย่อยถูกจัดเรียงโดยตัวจับเวลาเป็นงานที่ดำเนินการหรือทำซ้ำ ในความเป็นจริงมันเป็นคลาสที่มีวิธีการเรียกใช้และรหัสที่ต้องดำเนินการอย่างสม่ำเสมอจะถูกวางลงในตัววิธีการเรียกใช้
Java เปิดตัว Timer Class Timer ใน JDK1.3 จากนั้น Doulea ได้พัฒนา SchedulethreadPoolexecutor ที่รองรับการทำมัลติเธรดหลังจาก JDK1.5 เมื่อพิจารณาจากการแสดงของหลังเราสามารถพิจารณาแทนที่ตัวจับเวลาได้อย่างสมบูรณ์
การเปรียบเทียบระหว่างตัวจับเวลาและ schedulethreadpoolexecutor:
1. ตัวจับเวลาเริ่มต้นด้วย JDK1.3 หลักการของมันคือการใช้อาร์เรย์ timertask เป็นคิวเพื่อเพิ่มงานเวลาทั้งหมดในคิวนี้ จากนั้นเริ่มเธรด เมื่อคิวว่างเปล่าเธรดจะบล็อก เมื่อมีข้อมูลในคิวเธรดจะลบ timertask เพื่อตัดสิน
ไม่ว่าจะเป็นเวลาที่ทันสมัยงานจะเริ่มทำงานหากเวลาทำงานน้อยกว่าหรือเท่ากับเวลาปัจจุบัน เนื่องจากลักษณะเธรดเดี่ยวมันนำปัญหาหลายอย่าง (รหัสรายละเอียดในภายหลัง):
ก่อนอื่นเมื่องานที่เราเพิ่มลงในตัวจับเวลานั้นใช้เวลานานเนื่องจากตัวจับเวลานี้จะดำเนินงานตัวจับเวลาในลักษณะลำดับเธรดเดียวมันจะส่งผลกระทบต่อการดำเนินงานที่ตามมาในเวลาต่อมา
รหัส Java
// ตัวอย่างของปัญหา: m_timer.scheduleatfixedrate (taskuseLongtime (), 1,000, 5000); m_timer.scheduleatfixedrate (ใหม่ tasknormal (), 5000, 3000); ผลการดำเนินงาน: 14:44:29: ตัวจับเวลานอนหลับ 10 วินาที 14:44:39: ตัวจับเวลานอนหลับ 14:44:39: ตัวจับเวลานอนหลับ 10 วินาที 14:44:49: งานปกติดำเนินการ 14:44:49: งานปกติ 14:44:49: งานปกติดำเนินการ 14:44:49: ตัวจับเวลากำลังนอนหลับ 10 วินาทีการวิเคราะห์ผลลัพธ์: งาน tasknormal ไม่สามารถรับประกันได้ว่าจะทำงานได้ทุก ๆ 3 วินาทีมันสามารถรอให้ TaskUlongtime ทำงานได้หลังจากเสร็จสิ้น
ประการที่สองเธรดในตัวจับเวลาจะจับข้อยกเว้น InterruptedException เท่านั้นดังนั้นหากงานเวลาที่กำหนดเองของเราไม่ได้รับข้อยกเว้นที่เป็นไปได้และทำให้เกิดข้อยกเว้นที่จะโยน
// ตัวอย่างที่ 2: m_timer.schedule (taskthrowexception ใหม่ (), 1000); m_timer.schedule (ใหม่ tasknormal (), 2000); ผลการดำเนินการ: 14:47:37: โยนข้อยกเว้นในเธรด "Timer-0" java.lang.runtimeException ที่ timer_test.timertest $ taskthrowexception.run (timertest.java:85) ที่ java.util.timerthread.mainloop (timer.java java.util.timerthread.run (timer.java:462) การวิเคราะห์ผลลัพธ์: หลังจากข้อยกเว้นถูกโยนทิ้งโดยงานงาน tasknormal ที่ตามมาจะไม่สามารถทำงานต่อไปได้
สิ่งนี้จะทำให้เธรดจับเวลาของเราหยุดเพื่อให้งานอื่น ๆ ที่ตามมาไม่สามารถดำเนินการได้
ประการที่สามมันไม่สามารถจัดการงานหลายเวลาที่เกิดขึ้นพร้อมกัน
// การวิเคราะห์คำถามสามข้อ: m_timer.scheduleatfixedrate (TaskuseLongtime ใหม่ ("Timer1"), 1,000, 15000); m_timer.scheduleatfixedrate (TaskuseLongtime ใหม่ ("Timer2"), 1,000, 15000); ผลการวิ่ง: 14:50:16: Timer1 กำลังนอนหลับ 10 วินาที 14:50:26: Timer2 นอนหลับ 10 วินาที 14:50:36: Timer2 กำลังนอนหลับ 10 วินาทีการวิเคราะห์ผลลัพธ์: เวลาเริ่มต้นของฉันคือ 1 วินาทีในภายหลังตัวอย่างรหัส:
แพ็คเกจ timer_test; นำเข้า java.text.simpledateFormat; นำเข้า java.util.date นำเข้า java.util.timer; นำเข้า java.util.timertask; Timertest ระดับสาธารณะ {// ตัวอย่างของปัญหา: m_timer.scheduleatfixedrate (taskuselongtime ใหม่ (), 1,000, 5000); m_timer.scheduleatfixedrate (ใหม่ tasknormal (), 5000, 3000); // ตัวอย่าง 2: // m_timer.schedule // m_timer.schedule (ใหม่ tasknormal (), 2000); // ตัวอย่างที่ 3: // m_timer.scheduleatfixedrate (taskuselongtime ใหม่ ("Timer1"), 1,000, 5000); // m_timer.scheduleatfixedrate (taskuseLongtime ใหม่ ("timer2"), 1,000, 5000);} คลาสส่วนตัว taskuseLongtime ขยาย timertask {สตริงส่วนตัว m_taskname = "ตัวจับเวลา"; run () {ลอง {system.out.println (getCurrentTime ()+":"+m_taskname+"นอนหลับ 10 วินาที"); thread.sleep (10,000);} catch (interruptedException e) {}}} คลาสส่วนตัว {system.out.println (getCurrentTime ()+": งานปกติที่ดำเนินการ");}} taskthrowexception คลาสส่วนตัวขยาย timertask {@Override โมฆะสาธารณะเรียกใช้ () {system.out.println (getCurrentTime ()+": โยนข้อยกเว้น"); SimpledateFormat ("HH: MM: SS") รูปแบบ (วันที่ใหม่ ());}}2.Schedulethreadpoolexecutor
Schedulethreadpoolexecutor เริ่มต้นด้วย JDK1.5 และเขียนโดย Mr. Doulea มันใช้การผสมผสานที่ชาญฉลาดของ Threadpoolexecutor และ DelayQueue เพื่อดำเนินการตามตัวจับเวลาแบบมัลติเธรดแบบมัลติเธรดให้เสร็จสิ้นการแก้ข้อบกพร่องสามข้อข้างต้นที่เกิดจากเธรดเดี่ยวในตัวจับเวลา
ปัญหาในคำถามที่ 1 คืองานที่ตามมาไม่สามารถเสร็จสิ้นได้ตรงเวลาเนื่องจากเธรดเดี่ยวดำเนินการตามลำดับ เราเห็นว่ามัลติเธรดสามารถแก้ปัญหานี้ได้อย่างง่ายดาย ในเวลาเดียวกันเราสังเกตเห็นว่าเวลาดำเนินการของ taskuselongtime คือ 10 วินาที (โปรดดูรหัสที่ตามมา) เรากำหนดเวลาช่วงเวลางาน 5 วินาที แต่จากผลลัพธ์เราพบว่าช่วงเวลาการดำเนินงานของเราคือ 10 วินาทีดังนั้นเราจึงสามารถตัดสินได้ว่า schedulethreadpoolexecutor ทำงานในโหมดต่อเธรดต่องาน
// ปัญหา 1: m_timer.scheduleatfixedrate (TaskuseLongtime (), 1,000, 5000, TimeUnit.milliseconds); m_timer.scheduleatfixedrate (ใหม่ tasknormal (), 1,000, 5000, timeunit.milliseconds); ผลการดำเนินการ: 14:54:37: งานปกติดำเนินการ 14:54:37: ตัวจับเวลานอนหลับ 10 วินาที 14:54:42: งานปกติดำเนินการ 14:54:47: งานปกติดำเนินการ 14:54:47: งานปกติดำเนินการตามปกติ 14:54:47
ในคำถามที่ 2 เราพบว่าเมื่อมีการโยนข้อยกเว้นการดำเนินการของงานจะไม่ส่งผลกระทบต่อการทำงานของงานอื่น ในเวลาเดียวกันเราพบว่าข้อยกเว้นของเราไม่ได้ถูกโยนลงไปในผลการวิ่ง นี่เป็นเพราะคลาส ScheduleTheRadPoolexecutor จะส่งคืนผลลัพธ์การรัน ScheduleDFuture หลังจากดำเนินงานที่กำหนดเวลา ไม่ว่าผลลัพธ์จะประสบความสำเร็จหรือมีข้อยกเว้นมันจะถูกบันทึกไว้ที่นี่
// ปัญหา 2: m_timer.scheduleatfixedrate (Taskthrowexception ใหม่ (), 1,000, 5000, TimeUnit.milliseconds); m_timer.scheduleatfixedrate (ใหม่ tasknormal (), 1,000, 5000, timeunit.milliseconds); ผลการดำเนินการ: 14:58:36: โยนข้อยกเว้น 14:58:36: งานปกติดำเนินการ 14:58:41: งานปกติดำเนินการ 14:58:46: งานปกติดำเนินการ 14:58:46: งานปกติดำเนินการ 14:58:46: งานปกติดำเนินการ 14:58:51: งานปกติ
คำถามที่ 3 เนื่องจากเป็นแบบมัลติเธรดเราสามารถมั่นใจได้ว่างานเวลาของเราสามารถดำเนินการได้ในเวลาเดียวกัน
// ปัญหา 3: m_timer.scheduleatfixedrate (TaskuseLongtime ใหม่ ("Timer1"), 1,000, 5000, TimeUnit.milliseconds); m_timer.scheduleatfixedrate (TaskuseLongtime ใหม่ ("Timer2"), 1,000, 5000, TimeUnit.milliseconds); ผลการวิ่ง: 15:01:12: ตัวจับเวลา 1 นอนหลับ 10 วินาที 15:01:12: ตัวจับเวลา 2 นอนหลับ 10 วินาที 15:01:22: ตัวจับเวลา 2 นอนหลับ 10 วินาที 15:01:22: จับเวลา 2 นอน 10 วินาที 15:01:22 15:01:22: ตัวจับเวลา 2 นอนหลับ 10 วินาที 15:01:22: ตัวจับเวลา 2 นอนหลับ 10 วินาที 15:01:22: ตัวจับเวลา 2 นอนหลับ 10 วินาที 15:01:22: จับเวลา 2 นอน 10 วินาที 15:01:22: จับเวลา 2 15:01:22: ตัวจับเวลา 2 นอนหลับ 10 วินาที 15:01:22: ตัวจับเวลา 2 นอนหลับ 10 วินาที 15:01:22: ตัวจับเวลา 2 นอนหลับ 10 วินาที 15:01:22: จับเวลา 2 นอน 10 วินาที 15:01:22: จับเวลา 10: Timer2 วินาที 15:01:32: Timer2 นอนหลับ 10 วินาทีรหัสรายละเอียด:
แพ็คเกจ timer_test; นำเข้า java.text.simpledateFormat; นำเข้า java.util.date นำเข้า java.util.concurrent.callable; นำเข้า java.util.concurrent.scheduledthreadpoolexecutor; scheduledThreadPoolexecutor m_timer = ใหม่ scheduledThreadPoolexecutor (10); โมฆะคงที่สาธารณะหลัก (สตริง [] args) {schedulethreadpoolexecutortest timertest = new SchedulethreadPoolexecutest (); timertest.test () {timerTest.Shutdown ();}} การปิดการปิดโมฆะสาธารณะ () {m_timer.shutdown ();} การทดสอบโมฆะสาธารณะ () {// คำถาม 1: // m_timer.scheduleatfixedrate // m_timer.scheduleatfixedrate (ใหม่ tasknormal (), 1,000, 5000, timeunit.milliseconds); // คำถามที่ 2: // m_timer.scheduleatfixedrate (taskthrowexception (), 1,000, 5000, timeunit.milliseconds); // m_timer.scheduleatfixedrate (ใหม่ tasknormal (), 1,000, 5000, timeunit.milliseconds); // ปัญหา 3: m_timer.scheduleatfixedrate (TaskuseLongtime ใหม่ ("Timer1"), 1,000, 5000, TimeUnit.milliseconds); M_Timer.ScheduleatFixedrate callable <teger>, runnable {สตริงส่วนตัว m_taskname = "ตัวจับเวลา"; taskuselongtime ส่วนตัว () {} taskuseLongtime ส่วนตัว (สตริง taskname) {m_taskname = taskname;} โมฆะสาธารณะ Run () {ลอง {system.out.println วินาที "); thread.sleep (10,000);} catch (interruptedException e) {}} การเรียกใช้จำนวนเต็มสาธารณะ () โยนข้อยกเว้น {run (); return 0;}}@uspresswarnings (" ไม่ได้ใช้ ") {system.out.println (getCurrentTime ()+": งานปกติที่ดำเนินการ");}}@suppresswarnings ("ไม่ได้ใช้") คลาสส่วนตัว taskthrowexception ใช้ callable <teger> run () {system.out.println (getCurrentTime ()+": Throw Exception"); โยน runtimeException ใหม่ ();}} สตริงส่วนตัว getCurrentTime () {return New SimpleDateFormat ("HH: MM: SS")สรุป
ข้างต้นเป็นเรื่องเกี่ยวกับการอภิปรายสั้น ๆ ของบทความนี้เกี่ยวกับประวัติการพัฒนาของตัวจับเวลา Java และฉันหวังว่ามันจะเป็นประโยชน์กับทุกคน เพื่อนที่สนใจสามารถอ้างถึงเว็บไซต์นี้ต่อไปได้:
Java ใช้การแยกรหัสตัวจับเวลาอย่างง่าย
หลักการและการใช้งานของตัวจับเวลา Java Multithreaded Timer
ตัวอย่างรหัสของวิธีการใช้ตัวจับเวลา Java Timer
หากมีข้อบกพร่องใด ๆ โปรดฝากข้อความไว้เพื่อชี้ให้เห็น ขอบคุณเพื่อนที่ให้การสนับสนุนเว็บไซต์นี้!