เมื่อเร็ว ๆ นี้ฉันพบข้อกำหนดใหม่ในโครงการซึ่งคือการใช้ฟังก์ชั่นที่สามารถเพิ่มงานที่กำหนดเวลาแบบไดนามิก เมื่อพูดถึงเรื่องนี้บางคนอาจพูดได้ว่าง่ายแค่ใช้ควอตซ์มันง่ายและหยาบ อย่างไรก็ตามเฟรมเวิร์กควอตซ์นั้นหนักเกินไปและโครงการขนาดเล็กไม่ง่ายต่อการใช้งาน แน่นอนว่าบางคนอาจบอกว่า JDK ให้อินเทอร์เฟซตัวจับเวลาซึ่งเพียงพออย่างสมบูรณ์ อย่างไรก็ตามข้อกำหนดของโครงการของเราเป็นรุ่นมัลติเธรดที่สมบูรณ์ในขณะที่ตัวจับเวลาเป็นเธรดเดี่ยวดังนั้นในที่สุดผู้เขียนก็เลือกพูลเธรดของ JDK
พูลเธรดคืออะไร
Java จัดหาพูลเธรดสี่ประเภทผ่านผู้บริหารคือ:
newcachedthreadpool: สร้างพูลเธรดที่แคชได้ หากความยาวพูลเธรดเกินความต้องการการประมวลผลคุณสามารถรีไซเคิลเธรดที่ไม่ได้ใช้งานได้อย่างยืดหยุ่น หากไม่มีการรีไซเคิลให้สร้างเธรดใหม่
newfixedthreadpool: สร้างพูลเธรดที่มีความยาวคงที่ซึ่งสามารถควบคุมจำนวนเธรดที่เกิดขึ้นพร้อมกันได้สูงสุดและเธรดส่วนเกินจะรอในคิว
NewscheduledThreadPool: สร้างพูลเธรดที่มีความยาวคงที่ซึ่งรองรับการดำเนินงานตามเวลาและเป็นระยะ
NewsingLetHreadExecutor: สร้างพูลเธรดเดี่ยวซึ่งจะใช้เธรดคนงานที่ไม่ซ้ำกันเพื่อดำเนินงานเพื่อให้มั่นใจว่างานทั้งหมดจะดำเนินการตามลำดับที่ระบุ (FIFO, LIFO, ลำดับความสำคัญ)
โปสเตอร์ใช้ NewscheduledThreadPool ในโครงการ นั่นคือทั้งหมด ไม่ว่าคุณจะมีโปสเตอร์กี่ตัวคุณจะแสดงทักษะของคุณ Google มันและมันเยอะมาก
รับบริการพูลเธรด
ผู้เขียนใช้โหมด Singleton เพื่อรับบริการของพูลเธรด รหัสมีดังนี้:
/*** การสร้างพูลเธรด * @author wuhf * @date 2018/01/16 */คลาสสาธารณะ Threadpoolutils {ส่วนตัวคงที่ scheduleDexecutorservice ExecutorService; Private Threadpoolutils () {// สร้างพูลเธรดด้วยตนเอง ExecutorService = ใหม่ ScheduleDTHREADPOOLEXECUTOR (10, ใหม่ BASSICTHREADFACTORY.BUILDER (). NamingPattern ("SyncData-Schedule-Pool-%D"). Daemon (จริง) .build ()); } คลาสคงที่คลาสคงที่ pluginconfigholder {ส่วนตัวสุดท้ายคงที่ threadpoolutils อินสแตนซ์ = new Threadpoolutils (); } public Static threadpoolutils getInstance () {return pluginconfigholder.instance; } สาธารณะ scheduleDexecutorService getThreadPool () {return executorService; -การขัดจังหวะการใช้งานรหัสเธรดที่รัน
ฉันจะไม่พูดเรื่องไร้สาระมากรหัสมีดังนี้:
/*** งานในพูลเธรดถูกขัดจังหวะ */คลาสสาธารณะ InterruptHread ใช้งาน Runnable {Private Int Num; การขัดจังหวะสาธารณะ (int num) {this.num = num; } โมฆะคงที่สาธารณะหลัก (สตริง [] args) พ่น InterruptedException {เธรด interruptHread = เธรดใหม่ (ใหม่ interruptHread (1)); ScheduledFuture <?> t = threadpoolutils.getInstance (). getThreadPool (). ScheduleatFixedrate (InterruptHread, 0,2, TimeUnit.Seconds); InterruptThread InterruptHread1 = New InterruptThread (2); threadpoolutils.getInstance (). getThreadPool (). scheduleatfixedrate (interruptthread1,0,2, timeunit.seconds); InterruptThread InterruptHread2 = New InterruptThread (3); threadpoolutils.getInstance (). getThreadPool (). scheduleatfixedrate (interruptHread2,0,2, timeUnit.Seconds); thread.sleep (5000); // ยกเลิกการเรียกใช้เธรด interrupthread t.cancel (จริง); ในขณะที่ (จริง) {}} @Override โมฆะสาธารณะเรียกใช้ () {system.out.println ("นี่คือเธรด" + num); -บันทึกที่ติดอยู่
เมื่อโปสเตอร์ใช้รหัสต่อไปนี้ทันใดนั้นเขาก็คิดถึงวิธีหยุดเธรดจากการทำงานเมื่อต้องหยุดงานเวลานี้
threadpoolutils.getInstance (). getThreadPool (). scheduleatfixedrate (interrupthread, 0,2, timeUnit.seconds);
เนื่องจากฉันมีความต้องการเช่นนี้ให้ Google มัน หลังจากค้นหาเป็นส่วนใหญ่ฉันไม่สามารถหาข้อมูลที่เกี่ยวข้องได้ พวกเขาทั้งหมดเป็นการวิเคราะห์เชิงลึกของพูลเธรด Java หรือตัวแปรระดับโลกหรืออะไรบางอย่างไม่พบวิธีแก้ปัญหาเพื่อตอบสนองผู้เขียน
เนื่องจากไม่มีเธรดลองดูที่ซอร์สโค้ดพื้นฐานของ ScheduleatFixedrate เพื่อดูว่ามันคืออะไร ตามที่คาดไว้ฉันเห็นการใช้งานเฉพาะของเมธอด scheduleatfixedrate ในซอร์สโค้ดและพบว่าค่าส่งคืนคือ scheduledfuture
Public ScheduledFuture <?> ScheduleatFixEdrate (คำสั่ง runnable, Long Initialdelay, ระยะยาว, หน่วย TimeUnit) {ถ้า (Command == NULL || UNIT == NULL) โยน nullPoInterexception ใหม่ (); ถ้า (ระยะเวลา <= 0) โยน unlegalargumentException ใหม่ (); ScheduledFutureTask <Void> SFT = ใหม่ scheduledFutureTask <Void> (คำสั่ง, null, triggertime (initialdelay, unit), unit.tonanos (ระยะเวลา)); runnablecheduledfuture <Void> t = decorateTask (คำสั่ง, sft); sft.outerTask = t; delayedExecute (t); กลับ t; -จากนั้นมาดูว่ามีอะไรอยู่ข้างใน ScheduledFuture มันไม่ทำให้โปสเตอร์ผิดหวังและฉันเห็นสิ่งนี้
บูลีนสาธารณะยกเลิก (บูลีน Mayinterruptifrunning) {บูลีนยกเลิก = super.cancel (mayinterruptifrunning); if (ยกเลิก && removeCancel && heapIndex> = 0) ลบ (นี้); return canceled;} // ลบเธรดปัจจุบันออกจากบูลีนสาธารณะที่กำลังรันของเธรดลบ (งานที่เรียกใช้) {บูลีนลบ = workqueue.remove (งาน); Tryterminate (); // ในกรณีปิดตัวลองตรวจสอบว่า super.cancel (Mayinterruptifrunning) คืออะไร เราเห็นสิ่งนี้
// หยุดเธรดที่ทำงานโดยเรียกใช้วิธีการขัดจังหวะของเกลียวบูลีนสาธารณะยกเลิก (บูลีนเมย์อินเทอร์มิฟฟรันนิ่ง) {ถ้า (! (สถานะ == ใหม่ && unsafe.compareandswapint (นี่, stateoffset, ใหม่, mayinterruptifrunning? ลอง {// ในกรณีที่เรียกใช้เพื่อขัดจังหวะการโยนข้อยกเว้นถ้า (mayinterruptifrunning) {ลอง {เธรด t = runner; ถ้า (t! = null) t.interrupt (); } ในที่สุด {// สถานะสุดท้าย unsafe.putOrderEdInt (นี่, stateOffset, ถูกขัดจังหวะ); }}} ในที่สุด {finishcompletion (); } return true; -ปัญหาทั้งหมดที่นี่ได้รับการแก้ไข
มาสรุปกันเถอะ
มีวิธีแก้ปัญหาที่ยากในโครงการเสมอ เมื่อ Google หาไม่ง่ายอาจเป็นวิธีที่ดีในการค้นหาซอร์สโค้ดของ JDK