Java Timer เทียบกับ ExecutorService?


263

java.util.Timerฉันมีรหัสที่ฉันกำหนดการงานโดยใช้ ฉันมองไปรอบ ๆ และเห็นExecutorServiceสามารถทำเช่นเดียวกัน ดังนั้นคำถามนี้ตรงนี้คุณเคยใช้TimerและExecutorServiceจัดตารางเวลางานอะไรคือสิ่งที่คุณจะได้รับจากการใช้มากกว่าคนอื่น?

ยังต้องการตรวจสอบว่ามีใครใช้Timerชั้นเรียนและพบปัญหาใด ๆ ซึ่งExecutorServiceแก้ไขได้สำหรับพวกเขา


1
และถ้าคุณต้องการบางสิ่งบางอย่างแม้กระทั่ง featurefull เพิ่มเติมโปรดดูควอทซ์ มันช่วยให้คุณควบคุมงานได้มากขึ้นรวมถึง cron เช่นการจัดตารางเวลาการจัดตารางเวลาแบบคลัสเตอร์การควบคุมแต่ละงาน (แนวคิดต่าง ๆ เช่นการทำงานครั้งละครั้งการอ้างอิง ฯลฯ ) --Tim
Tim

คำตอบ:


313

ตามJava Concurrency ในการปฏิบัติ :

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

หากคุณสามารถใช้ScheduledThreadExecutorแทนTimerทำเช่นนั้น

อีกอย่างหนึ่ง ... ในขณะที่ScheduledThreadExecutorไม่มีให้บริการในไลบรารี Java 1.4 มีBackport ของ JSR 166 ( java.util.concurrent) ถึง Java 1.2, 1.3, 1.4ซึ่งมีScheduledThreadExecutorคลาส


63

หากคุณพร้อมใช้งานก็เป็นเรื่องยากที่จะคิดว่าเหตุผลใดที่จะไม่ใช้เฟรมเวิร์กผู้ปฏิบัติการ Java 5 โทรศัพท์:

ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();

จะให้คุณScheduledExecutorServiceด้วยฟังก์ชั่นที่คล้ายกันกับTimer(เช่นมันจะเป็นเธรดเดียว) แต่การเข้าถึงที่อาจจะปรับขนาดได้เล็กน้อย (ภายใต้ประทุนนั้นจะใช้โครงสร้างที่เกิดขึ้นพร้อมกันมากกว่าการประสานสมบูรณ์เช่นเดียวกับTimerชั้นเรียน) การใช้ a ScheduledExecutorServiceยังช่วยให้คุณได้เปรียบเช่น:

  • คุณสามารถปรับแต่งได้ตามต้องการ (ดูnewScheduledThreadPoolExecutor()หรือScheduledThreadPoolExecutorคลาส)
  • การประมวลผล 'one off' สามารถส่งคืนผลลัพธ์

เกี่ยวกับเหตุผลเดียวที่Timerฉันคิดได้คือ:

  • มันสามารถใช้ได้ก่อน Java 5
  • คลาสที่คล้ายกันนั้นมีให้ใน J2ME ซึ่งสามารถทำให้การย้ายแอปพลิเคชันของคุณง่ายขึ้น (แต่มันก็ไม่ยากที่จะเพิ่มเลเยอร์ที่เป็นนามธรรมของเลเวลในกรณีนี้)

1
อีกเหตุผลหนึ่งสำหรับการใช้TimerTaskอาจจะเป็นความพร้อมของวิธีการที่ไม่ได้ดูเหมือนจะมีเทียบเท่าใดscheduledExecutionTime()ScheduledExecutorService
Rohit Agarwal

3
หมายเหตุอื่น: ฉันกำลังเขียนความคิดเห็นนี้ใน 2k17 ไม่มี J2ME อีกต่อไป มันตายไปแล้ว
msangel

1
Java Timer-class เส็งเคร็ง
JohnyTex

26

ExecutorService มีความใหม่กว่าและทั่วไปกว่า ตัวจับเวลาเป็นเพียงเธรดที่ใช้งานสิ่งที่คุณกำหนดไว้เป็นระยะ

ExecutorService อาจเป็นเธรดพูลหรือแม้แต่กระจายข้ามระบบอื่น ๆ ในคลัสเตอร์และทำสิ่งต่าง ๆ เช่นการดำเนินการแบทช์ครั้งเดียว ฯลฯ ...

เพียงแค่ดูสิ่งที่แต่ละข้อเสนอในการตัดสินใจ


16

ต่อไปนี้เป็นแนวทางปฏิบัติที่ดีเพิ่มเติมเกี่ยวกับการใช้ตัวจับเวลา:

http://tech.puredanger.com/2008/09/22/timer-rules/

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


8

จากหน้าเอกสารของ Oracle ในScheduledThreadPoolExecutor

ThreadPoolExecutorว่านอกจากนี้ยังสามารถกำหนดเวลาที่จะเรียกใช้คำสั่งหลังจากที่ล่าช้าได้รับหรือการดำเนินการเป็นระยะ ๆ คลาสนี้เหมาะสำหรับการจับเวลาเมื่อต้องการเธรดผู้ทำงานหลายคนหรือเมื่อต้องการความยืดหยุ่นหรือความสามารถเพิ่มเติมของ ThreadPoolExecutor (ซึ่งคลาสนี้ขยาย) จำเป็นต้องมี

ExecutorService/ThreadPoolExecutorหรือScheduledThreadPoolExecutorเป็นตัวเลือกที่ชัดเจนเมื่อคุณมีเธรดผู้ทำงานหลายคน

ข้อดีExecutorServiceกว่าTimer

  1. Timerไม่สามารถใช้ประโยชน์ของแกน CPU ที่มีแตกต่าง ExecutorServiceโดยเฉพาะอย่างยิ่งกับงานต่างๆโดยใช้รสชาติExecutorServiceเหมือนForkJoinPool
  2. ExecutorServiceให้ API การทำงานร่วมกันหากคุณต้องการการประสานงานระหว่างหลายงาน สมมติว่าคุณต้องส่งจำนวนงานของคนงาน N และรอให้งานทั้งหมดเสร็จ คุณสามารถบรรลุผลได้อย่างง่ายดายด้วยinvokeAll API หากคุณต้องการบรรลุเป้าหมายเดียวกันกับหลาย ๆTimerงานมันจะไม่ง่ายเลย
  3. ThreadPoolExecutorมอบ API ที่ดีกว่าสำหรับการจัดการวงจรชีวิตของเธรด

    กลุ่มเธรดแก้ไขปัญหาที่แตกต่างกันสองประการ: โดยปกติแล้วพวกเขาจะให้ประสิทธิภาพที่ดีขึ้นเมื่อเรียกใช้งานแบบอะซิงโครนัสจำนวนมากเนื่องจากลดค่าใช้จ่ายในการเรียกใช้งานต่อภารกิจ งาน แต่ละ ThreadPoolExecutor ยังเก็บรักษาสถิติพื้นฐานบางอย่างเช่นจำนวนงานที่เสร็จสมบูรณ์

    ข้อดีไม่กี่:

    คุณสามารถสร้าง / จัดการ / ควบคุมวงจรชีวิตของเธรดและเพิ่มประสิทธิภาพค่าใช้จ่ายในการสร้างเธรด

    ข คุณสามารถควบคุมการประมวลผลของงาน (Work Stealing, ForkJoinPool, invokeAll) เป็นต้น

    ค. คุณสามารถติดตามความคืบหน้าและสุขภาพของกระทู้

    d ให้กลไกการจัดการข้อยกเว้นที่ดีกว่า


5

เหตุผลของฉันในการเลือกใช้ตัวจับเวลามากกว่า Executors.newSingleThreadScheduledExecutor () คือฉันได้รับโค้ดที่สะอาดกว่าเมื่อฉันต้องการให้ตัวจับเวลาทำงานบนเธรด daemon

เปรียบเทียบ

private final ThreadFactory threadFactory = new ThreadFactory() {
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        t.setDaemon(true);
        return t;
    }
};
private final ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor(threadFactory); 

กับ

private final Timer timer = new Timer(true);

ฉันทำสิ่งนี้เมื่อฉันไม่ต้องการความแข็งแกร่งของตัวบริการ

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