2. บทนำ
เทคโนโลยีมัลติเธรดส่วนใหญ่แก้ปัญหาของการดำเนินการหลายเธรดในหน่วยโปรเซสเซอร์ มันสามารถลดเวลาว่างของหน่วยโปรเซสเซอร์ได้อย่างมีนัยสำคัญและเพิ่มความสามารถในการรับส่งข้อมูลของหน่วยโปรเซสเซอร์ อย่างไรก็ตามค่าใช้จ่ายของการสร้างเธรดบ่อยครั้งมีขนาดใหญ่มาก ดังนั้นวิธีลดส่วนนี้ของค่าใช้จ่ายคุณต้องพิจารณาใช้พูลเธรด พูลเธรดเป็นคอนเทนเนอร์เธรดซึ่งจะดำเนินการจำนวนเธรดที่ได้รับการจัดอันดับเท่านั้น พูลเธรดใช้ในการจัดการจำนวนเธรดที่กำหนดไว้เหล่านี้
3. แผนภาพโครงสร้างคลาสที่เกี่ยวข้องกับพูลเธรด
ในหมู่พวกเขาสิ่งสำคัญสำหรับเราที่จะใช้คือคลาส Threadpoolexecutor
4. วิธีสร้างพูลเธรด
โดยทั่วไปเรามีวิธีการต่อไปนี้ในการสร้างพูลเธรด:
1. ใช้คลาสโรงงาน Executors
ผู้ดำเนินการส่วนใหญ่มีวิธีการต่อไปนี้เพื่อสร้างพูลเธรด:
มาดูตัวอย่างการใช้งานด้านล่าง:
1) newfixedthreadpool (คงที่พูลเธรด)
คลาสสาธารณะที่ได้รับ {encutorService pool = executors.newFixedThreadPool (5); // สร้างพูลเธรดที่มีขนาดคงที่ 5 สำหรับ (int i = 0; i <10; i ++) {pool.submit } pool.shutdown (); }} คลาสสาธารณะ MyThread ขยายเธรด {@Override โมฆะสาธารณะเรียกใช้ () {System.out.println (thread.currentThread (). getName () + "การดำเนินการ ... "); -ผลการทดสอบมีดังนี้:
Pool-1-Thread-1 กำลังดำเนินการ - -
Pool-1-Thread-2 กำลังดำเนินการ - -
Pool-1-Thread-3 กำลังดำเนินการ - -
Pool-1-Thread-2 กำลังดำเนินการ - -
Pool-1-Thread-3 กำลังดำเนินการ - -
Pool-1-Thread-2 กำลังดำเนินการ - -
Pool-1-Thread-2 กำลังดำเนินการ - -
Pool-1-Thread-3 กำลังดำเนินการ - -
Pool-1-Thread-5 กำลังดำเนินการ - -
Pool-1-Thread-4 กำลังดำเนินการ - -
พูลเธรดขนาดคงที่: สร้างเธรดทุกครั้งที่ส่งงานจนกว่าเธรดจะมีขนาดสูงสุดของพูลเธรด ขนาดของพูลเธรดจะยังคงไม่เปลี่ยนแปลงเมื่อถึงค่าสูงสุด หากเธรดสิ้นสุดลงเนื่องจากข้อยกเว้นการดำเนินการพูลเธรดจะเพิ่มเธรดใหม่
2) NewsingLetHreadExecutor (พูลเธรดเดี่ยว)
ระดับสาธารณะ singlethreadpool {โมฆะสาธารณะคงที่หลัก (สตริง [] args) {executorService pool = executors.newsinglethreathedexecutor (); // สร้างพูลเธรดเดี่ยวสำหรับ (int i = 0; i <100; i ++) {pool.submit } pool.shutdown (); -ผลการทดสอบมีดังนี้:
Pool-1-Thread-1 กำลังดำเนินการ - -
Pool-1-Thread-1 กำลังดำเนินการ - -
Pool-1-Thread-1 กำลังดำเนินการ - -
Pool-1-Thread-1 กำลังดำเนินการ - -
Pool-1-Thread-1 กำลังดำเนินการ - -
Pool-1-Thread-1 กำลังดำเนินการ - -
Pool-1-Thread-1 กำลังดำเนินการ - -
Pool-1-Thread-1 กำลังดำเนินการ - -
Pool-1-Thread-1 กำลังดำเนินการ - -
Pool-1-Thread-1 กำลังดำเนินการ - -
พูลเธรดแบบเธรดเดี่ยว: พูลเธรดนี้มีเพียงเธรดเดียวที่ทำงานได้ซึ่งหมายความว่าการดำเนินการอนุกรมแบบเธรดเดี่ยวของงานทั้งหมด หากเธรดที่ไม่ซ้ำกันนี้สิ้นสุดลงเนื่องจากข้อยกเว้นจะมีเธรดใหม่ที่จะแทนที่ พูลเธรดนี้ทำให้มั่นใจได้ว่าคำสั่งการดำเนินการของงานทั้งหมดจะดำเนินการตามลำดับของการส่งงาน
3) NewscheduledThreadpool
ชั้นเรียนสาธารณะ ScheduleDTHREADPOOL {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {scheduleDexecutorService pool = executors.newscheduledThreadPool (6); สำหรับ (int i = 0; i <10,000; i ++) {pool.submit (ใหม่ Mythread ()); } pool.schedule (ใหม่ mythread (), 1,000, timeunit.milliseconds); pool.schedule (New Mythread (), 1,000, TimeUnit.milliseconds); pool.shutdown (); -ผลการทดสอบมีดังนี้:
Pool-1-Thread-1 กำลังดำเนินการ - -
Pool-1-Thread-6 กำลังดำเนินการ - -
Pool-1-Thread-5 กำลังดำเนินการ - -
Pool-1-Thread-4 กำลังดำเนินการ - -
Pool-1-Thread-2 กำลังดำเนินการ - -
Pool-1-Thread-3 กำลังดำเนินการ - -
Pool-1-Thread-4 กำลังดำเนินการ - -
Pool-1-Thread-5 กำลังดำเนินการ - -
Pool-1-Thread-6 กำลังดำเนินการ - -
Pool-1-Thread-1 กำลังดำเนินการ - -
- -
Pool-1-Thread-4 กำลังดำเนินการ - -
Pool-1-Thread-1 กำลังดำเนินการ - -
สองเธรดสุดท้ายของผลการทดสอบจะเริ่มดำเนินการหลังจากล่าช้า 1s พูลเธรดนี้รองรับความต้องการเวลาและการดำเนินงานเป็นระยะ ๆ
4) Newcachedthreadpool (พูลเธรดที่แคช)
คลาสสาธารณะ cachedthreadpool {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {executorservice pool = executors.newcachedthreadpool (); สำหรับ (int i = 0; i <100; i ++) {pool.submit (New Mythread ()); } pool.shutdown (); -ผลการทดสอบมีดังนี้:
Pool-1-Thread-5 กำลังดำเนินการ - -
Pool-1-Thread-7 กำลังดำเนินการ - -
Pool-1-Thread-5 กำลังดำเนินการ - -
Pool-1-Thread-16 กำลังดำเนินการ - -
Pool-1-Thread-17 กำลังดำเนินการ - -
Pool-1-Thread-16 กำลังดำเนินการ - -
Pool-1-Thread-5 กำลังดำเนินการ - -
Pool-1-Thread-7 กำลังดำเนินการ - -
Pool-1-Thread-16 กำลังดำเนินการ - -
Pool-1-Thread-18 กำลังดำเนินการ - -
Pool-1-Thread-10 กำลังดำเนินการ - -
พูลเธรดที่แคชได้: หากขนาดของพูลเธรดเกินเธรดที่จำเป็นในการประมวลผลงานเธรดที่ไม่ได้ใช้งานบางอย่าง (ไม่มีการดำเนินการงานใน 60 วินาที) จะถูกรีไซเคิล เมื่อจำนวนงานเพิ่มขึ้นพูลเธรดนี้สามารถเพิ่มเธรดใหม่ได้อย่างชาญฉลาดเพื่อจัดการงาน พูลเธรดนี้ไม่ได้ จำกัด ขนาดพูลเธรดซึ่งขึ้นอยู่กับขนาดเธรดสูงสุดที่ระบบปฏิบัติการ (หรือ JVM) สามารถสร้างได้
อย่างเป็นทางการชี้ให้เห็นว่าโปรแกรมเมอร์ใช้วิธีการของผู้ดำเนินการโรงงานที่สะดวกยิ่งขึ้น NewCachedThreadPool () (พูลเธรดที่ไม่ได้ จำกัด ซึ่งสามารถทำการรีไซเคิลเธรดอัตโนมัติ), Executors.NewFixedThreadPool (int) (พูลเกลียวขนาดคงที่) พูลเธรดเหล่านี้ถูกกำหนดไว้ล่วงหน้าโดยการกำหนดค่าเริ่มต้นสำหรับสถานการณ์การใช้งานส่วนใหญ่
2. สืบทอดคลาส Threadpoolexecutor และคัดลอกวิธีตัวสร้างของคลาสแม่
ก่อนที่จะแนะนำวิธีนี้ให้วิเคราะห์รหัสพื้นฐานก่อนหน้านี้สำหรับการสร้างพูลเธรด?
ผู้บริหารระดับสาธารณะ {Public Static ExecutorService newFixedThreadPool (int nthreads) {ส่งคืน ThreadPoolexecutor ใหม่ (nthreads, nthreads, 0l, timeunit.milliseconds, LinkedBlockingQueue ใหม่ <runnable> (); } public executorService newsingLetHreatHreadExecutor () {ส่งคืน FinalizabledElegatedExecutorService ใหม่ (ใหม่ ThreadPoolexecutor (1, 1, 0L, TimeUnit.Milliseconds, LinkedBlockingQueue ใหม่ <runnable> ()); -จากรหัสพื้นฐานของคลาสผู้บริหารระดับโรงงานเราจะเห็นได้ว่าวิธีการที่จัดทำโดยคลาสโรงงานเพื่อสร้างพูลเธรดจะถูกนำมาใช้จริงโดยการสร้าง Threadpoolexecutor รหัสวิธีการสร้าง ThreadPoolexecutor มีดังนี้:
Public Threadpoolexecutor (int corepoolsize, int maximumpoolsize, jeepalivetime ยาว, หน่วยเวลา, blockkingqueue <runnable> workqueue, ThreadFactory ThreadFactory, Handler HESHIVE <FOLSIZE orderalargumentException (); if (workqueue == null || threadFactory == null || handler == null) โยน nullpointerexception ใหม่ (); this.corepoolsize = corepoolsize; this.maximumpoolsize = maximumpoolsize; this.workqueue = workqueue; this.keepalivetime = unit.tonanos (keepalivetime); this.threadFactory = ThreadFactory; this.handler = Handler; -
จากนั้นมาพูดคุยเกี่ยวกับวิธีการสร้าง Threadpoolexecutor ในวิธีการก่อสร้างนี้ส่วนใหญ่มีพารามิเตอร์ต่อไปนี้:
CorePoolsize-จำนวนเธรดที่บันทึกไว้ในพูลรวมถึงเธรดฟรี
Maximumpoolsize - จำนวนเธรดสูงสุดที่อนุญาตในพูล
KEDALIVETIME-เมื่อจำนวนเธรดมากกว่า CorePoolsize นี่เป็นเวลาที่ยาวที่สุดสำหรับเธรดที่ไม่ได้ใช้งานเพื่อรองานใหม่
หน่วย- หน่วยเวลาพารามิเตอร์ของ Keepalivetime
Workqueue-คิวที่ใช้รักษางานก่อนดำเนินการ คิวนี้จะรักษาเฉพาะงานที่รันได้ส่งโดยวิธีการดำเนินการ
ThreadFactory-โรงงานที่ใช้โดยผู้ดำเนินการเพื่อสร้างเธรดใหม่
Handler-ตัวจัดการที่ใช้เมื่อการดำเนินการถูกบล็อกเนื่องจากขอบเขตของเธรดและความจุคิว
ถัดไปพูดคุยเกี่ยวกับความสัมพันธ์ระหว่างพารามิเตอร์เหล่านี้ เมื่อพูลเธรดถูกสร้างขึ้นเมื่อไม่มีเธรดในพูลเธรด (โปรดทราบว่าไม่ใช่ว่ามีเธรดจำนวนหนึ่งถูกสร้างขึ้นทันทีที่สร้างพูลเธรด) เมื่อมีการเรียกวิธีการดำเนินการ () เพื่อเพิ่มงานพูลเธรดจะทำการตัดสินต่อไปนี้:
1) หากจำนวนเธรดที่ทำงานอยู่ในปัจจุบันน้อยกว่า corePoolsize จากนั้นสร้างเธรดใหม่ทันทีเพื่อทำงานนี้
2) หากจำนวนเธรดที่กำลังทำงานอยู่มากกว่าหรือเท่ากับ CorePoolsize งานนี้จะถูกใส่ลงในคิว
3) หากคิวพูลเธรดเต็ม แต่จำนวนเธรดที่ทำงานน้อยกว่า maximumpoolsize เธรดใหม่จะยังคงถูกสร้างขึ้นเพื่อทำงานนี้
4) หากคิวเต็มและจำนวนของเธรดที่รันอยู่ในปัจจุบันมากกว่าหรือเท่ากับ maximumpoolsize พูลเธรดจะจัดการงานปัจจุบันตามนโยบายการปฏิเสธ
5) เมื่อมีการดำเนินการงานเธรดจะใช้งานถัดไปจากคิวเพื่อดำเนินการ หากไม่มีงานที่จะดำเนินการในคิวเธรดจะไม่ได้ใช้งาน หากเวลาการอยู่รอดของ Keepalivetime เกินกว่าเธรดจะถูกรีไซเคิลโดยพูลเธรด (หมายเหตุ: เธรดการรีไซเคิลนั้นมีเงื่อนไขหากจำนวนเธรดที่ทำงานอยู่ในปัจจุบันมากกว่า corePoolsize เธรดจะถูกทำลายหากไม่มากกว่า corePoolsize เหตุใดจึงไม่ใช่ว่าเธรดจะถูกรีไซเคิลทันทีที่ไม่ได้ใช้งาน แต่มันต้องรอจนกว่าจะเกิน Keepalivetime ก่อนที่จะรีไซเคิลเธรด? เหตุผลนั้นง่ายมาก: เนื่องจากการสร้างและการทำลายของเธรดใช้มากและไม่สามารถสร้างและทำลายได้บ่อยครั้ง หลังจากที่เกินพิทักษ์พบว่ากระทู้นี้ไม่ได้ใช้จริงและมันจะถูกทำลาย ในกรณีนี้หน่วยแสดงถึงหน่วยเวลาของ Keepalivetime และคำจำกัดความของหน่วยมีดังนี้:
public enum timeunit {nanoseconds {// keepalivetime ใน nanoseconds}, microseconds {// keepalivetime ใน microseconds}, มิลลิวินาที {// keepalivetime ใน milliseconds} สองนาที Keepalivetime ในชั่วโมง} วัน {// keepalivetime ในวัน}; มาวิเคราะห์ซอร์สโค้ดด้านล่าง สำหรับสถานการณ์ข้างต้นซอร์สโค้ดที่เกี่ยวข้องส่วนใหญ่มีดังต่อไปนี้:
บูลีนส่วนตัว addifundercorepoolsize (runnable firsttask) {เธรด t = null; สุดท้าย reentrantlock mainlock = this.mainlock; mainlock.lock (); ลอง {if (poolsize <corepoolsize && runstate == การรัน) t = addThread (firsttask); } ในที่สุด {mainlock.unlock (); } ถ้า (t == null) ส่งคืนเท็จ; T.Start (); กลับมาจริง; - ในความเป็นจริงรหัสนี้ง่ายมาก ส่วนใหญ่อธิบายว่าหากพูลเธรดปัจจุบันมีขนาดเล็กกว่า corePoolsize เธรดใหม่จะถูกสร้างขึ้นเพื่อจัดการงาน
บูลีนส่วนตัว addifundermaximumpoolsize (runnable firsttask) {เธรด t = null; สุดท้าย reentrantlock mainlock = this.mainlock; mainlock.lock (); ลอง {if (poolsize <maximumpoolsize && runstate == Running) t = addThread (firstTask); } ในที่สุด {mainlock.unlock (); } ถ้า (t == null) ส่งคืนเท็จ; T.Start (); กลับมาจริง; -รหัสข้างต้นอธิบายว่าหากจำนวนพูลเธรดปัจจุบันน้อยกว่า maximumpoolsize เธรดจะถูกสร้างขึ้นเพื่อดำเนินการงาน
5. คิวพูลเธรด
คิวพูลเธรดมี 3 ประเภท:
Direct Commit: ตัวเลือกเริ่มต้นสำหรับคิวงานคือ Synchronousqueue ซึ่งส่งงานโดยตรงไปยังเธรดโดยไม่เก็บไว้ ที่นี่หากไม่มีเธรดที่สามารถเรียกใช้งานได้ทันทีพยายามที่จะคิวงานจะล้มเหลวดังนั้นการสร้างเธรดใหม่ นโยบายนี้หลีกเลี่ยงการล็อคเมื่อจัดการชุดคำขอที่อาจมีการพึ่งพาภายใน การส่งโดยตรงมักจะต้องใช้ maximumpoolsizes ที่ไม่มีขอบเขตเพื่อหลีกเลี่ยงการปฏิเสธงานที่ส่งใหม่ กลยุทธ์นี้ช่วยให้เธรดที่ไม่มีขอบเขตมีความเป็นไปได้ของการเติบโตเมื่อคำสั่งมาถึงอย่างต่อเนื่องโดยมีค่าเฉลี่ยที่คิวสามารถจัดการได้
คิวที่ไม่มีขอบเขต: การใช้คิวที่ไม่มีขอบเขต (ตัวอย่างเช่น LinkedBlockingQueue ที่ไม่มีความจุที่กำหนดไว้ล่วงหน้า) จะทำให้งานใหม่รอคิวเมื่อเธรด corePoolsize ทั้งหมดไม่ว่าง ด้วยวิธีนี้เธรดที่สร้างขึ้นจะไม่เกิน CorePoolsize (ค่าของ maximumpoolsize นั้นไม่ถูกต้อง) เมื่อแต่ละงานนั้นไม่ขึ้นกับงานอื่นอย่างสมบูรณ์นั่นคือการดำเนินงานจะไม่ส่งผลต่อกันและกันมันเหมาะสำหรับคิวที่ไม่มีขอบเขต ตัวอย่างเช่นในเซิร์ฟเวอร์หน้าเว็บ การคิวนี้สามารถใช้เพื่อจัดการคำขอระเบิดชั่วคราวและกลยุทธ์นี้อนุญาตให้เธรดที่ไม่มีขอบเขตมีความเป็นไปได้ของการเติบโตเมื่อคำสั่งมาถึงอย่างต่อเนื่องเกินค่าเฉลี่ยที่คิวสามารถจัดการได้
คิวที่มีขอบเขต: เมื่อใช้ maximumpoolsizes ที่ จำกัด คิวที่มีขอบเขต (เช่น ArrayblockingQueue) ช่วยป้องกันการอ่อนเพลียของทรัพยากร แต่อาจเป็นการยากที่จะปรับและควบคุม ขนาดคิวและขนาดสระสูงสุดอาจจำเป็นต้องแลกเปลี่ยนซึ่งกันและกัน: การใช้คิวขนาดใหญ่และสระว่ายน้ำขนาดเล็กสามารถลดการใช้งาน CPU ทรัพยากรระบบปฏิบัติการและการสลับค่าใช้จ่ายในบริบท แต่อาจส่งผลให้ปริมาณงานลดลงด้วยตนเอง หากงานถูกบล็อกบ่อยครั้ง (ตัวอย่างเช่นหากเป็นขอบเขต I/O) ระบบอาจกำหนดเวลาสำหรับเธรดมากกว่าที่คุณอนุญาต การใช้คิวขนาดเล็กมักจะต้องใช้ขนาดสระว่ายน้ำที่ใหญ่ขึ้นและมีการใช้งาน CPU ที่สูงขึ้น แต่อาจพบค่าใช้จ่ายในการกำหนดเวลาที่ยอมรับไม่ได้ซึ่งสามารถลดปริมาณงานได้
พูดคุยเกี่ยวกับคิวพูลเธรดด้านล่างแผนภาพโครงสร้างคลาสมีดังนี้:
1) Synchronousqueue
คิวสอดคล้องกับการส่งโดยตรงที่กล่าวถึงข้างต้น ก่อนอื่น Synchronousqueue นั้นไม่ได้ จำกัด ซึ่งหมายความว่าความสามารถในการจัดเก็บหมายเลขนั้นไม่ จำกัด อย่างไรก็ตามเนื่องจากลักษณะของคิวเองหลังจากเพิ่มองค์ประกอบคุณต้องรอให้เธรดอื่นพาพวกเขาออกไปก่อนที่คุณจะสามารถเพิ่มได้
2) LinkedBlockingQueue
คิวสอดคล้องกับคิวที่ไม่มีขอบเขตด้านบน
3) arrayblockingqueue
คิวสอดคล้องกับคิวที่มีขอบเขตด้านบน ArrayblockingQueue มี 3 ตัวต่อไปนี้:
Public ArrayblockingQueue (ความสามารถในการ int) {นี้ (ความจุ, เท็จ); } Public ArrayBlockingQueue (ความสามารถในการแสดงสินค้าบูลีน) {ถ้า (ความจุ <= 0) โยน unlegalargumentException ใหม่ (); this.items = (e []) วัตถุใหม่ [ความจุ]; ล็อค = ใหม่ reentrantlock (ยุติธรรม); notempty = lock.newCondition (); notfull = lock.newcondition (); } arrayblockingqueue สาธารณะ (ความจุ int, Boolean Fair, คอลเลกชัน <? ขยาย e> c) {นี้ (ความจุ, ยุติธรรม); ถ้า (ความจุ <C.Size ()) โยน unlegalargumentException ใหม่ (); สำหรับ (iterator <? ขยาย e> it = c.iterator (); it.hasnext ();) เพิ่ม (it.next ()); -มามุ่งเน้นไปที่งานนี้ Fair แสดงถึงกลยุทธ์การแข่งขันของเธรดการเข้าถึงคิว เมื่อเป็นจริงคิวการแทรกงานจะปฏิบัติตามกฎ FIFO ถ้าเท็จคุณสามารถ "ตัดคิว" ตัวอย่างเช่นหากมีงานมากมายที่เข้าคิวในขณะนี้เธรดได้เสร็จสิ้นงานและงานใหม่มาถึง หากเป็นเท็จงานนี้ไม่จำเป็นต้องเข้าคิวในคิว คุณสามารถตัดคิวโดยตรงแล้วดำเนินการ ดังที่แสดงในรูปด้านล่าง:
6. กลยุทธ์การดำเนินการปฏิเสธพูลเธรด
เมื่อจำนวนเธรดมาถึงค่าสูงสุดงานจะยังคงมาในเวลานี้และในเวลานี้ฉันต้องปฏิเสธที่จะยอมรับงาน
ThreadPoolexecutor อนุญาตให้ปรับแต่งนโยบายการดำเนินการเมื่อเพิ่มงานล้มเหลว คุณสามารถเรียกวิธีการ SetRejectEdExecutionHandler () ของพูลเธรดและแทนที่นโยบายที่มีอยู่ด้วยวัตถุที่ถูกปฏิเสธการกำหนด ExecutionHandler กลยุทธ์การประมวลผลเริ่มต้นที่จัดทำโดย ThreadPoolexecutor คือการทิ้งและโยนข้อมูลข้อยกเว้นโดยตรงในเวลาเดียวกัน ThreadPoolexecutor มีนโยบายที่มีอยู่ 4 ฉบับคือ:
threadpoolexecutor.abortpolicy: ระบุว่างานถูกปฏิเสธและมีข้อยกเว้นถูกโยนทิ้ง ซอร์สโค้ดมีดังนี้:
การทำ abortpolicy ระดับสาธารณะแบบคงที่ใช้การปฏิเสธ ExcutionHandler { /*** สร้าง <tt> abortpolicy </tt> * / Public Abortpolicy () {} / *** โยนปฏิเสธ ExpledExecutionException เสมอ * @param r งานที่เรียกใช้งานได้ร้องขอให้ดำเนินการ * @param e ผู้ดำเนินการพยายามที่จะดำเนินการงานนี้ * @throws ปฏิเสธ ExputExecutionException เสมอ */ โมฆะสาธารณะปฏิเสธการกำหนด (runnable r, threadpoolexecutor e) {โยน demnedExecutionException ใหม่ (); // การโยนข้อยกเว้น}}Threadpoolexecutor.discardpolicy: หมายความว่างานถูกปฏิเสธ แต่ไม่มีการกระทำใด ๆ ซอร์สโค้ดมีดังนี้:
DiscardPolicy ระดับสาธารณะแบบคงที่การใช้งาน DENGEDEXECUTIONHANDLER { /*** สร้าง <tt> DiscardPolicy </TT> * / Public DiscardPolicy () {} / *** ไม่ทำอะไรเลยซึ่งมีผลต่อการทิ้งงาน r * @param r งานที่เรียกใช้งานได้ร้องขอให้ดำเนินการ * @param e ผู้ดำเนินการพยายามที่จะดำเนินการงานนี้ */ โมฆะสาธารณะปฏิเสธการตรวจสอบ (runnable r, threadpoolexecutor e) {} // ปฏิเสธโดยตรง แต่ไม่ทำอะไรเลย}}Threadpoolexecutor.CallerRunspolicy: ระบุว่างานถูกปฏิเสธและงานจะถูกดำเนินการโดยตรงในเธรดของผู้โทร ซอร์สโค้ดมีดังนี้:
คลาสสแตติกสาธารณะ callerrunspolicy ใช้ DENGEDEXECUTIONHANDLER { /*** สร้าง <tt> callerrunspolicy </tt> * / Public CallerRunspolicy () {} / ** * ดำเนินการงาน R ในเธรดของผู้โทรเว้นแต่ผู้ดำเนินการ * ถูกปิดตัวลงซึ่งในกรณีนี้งานจะถูกยกเลิก * @param r งานที่เรียกใช้งานได้ร้องขอให้ดำเนินการ * @param e ผู้ดำเนินการพยายามที่จะดำเนินการงานนี้ */ โมฆะสาธารณะปฏิเสธการสอน (runnable r, threadpoolexecutor e) {ถ้า (! e.isshutdown ()) {rrun (); // ดำเนินการงานโดยตรง}}}Threadpoolexecutor.discardoldestpolicy: หมายความว่างานแรกในคิวงานจะถูกยกเลิกก่อนจากนั้นงานจะถูกเพิ่มเข้าไปในคิว ซอร์สโค้ดมีดังนี้:
คลาสสแตติกสาธารณะ DiscardoldestPolicy ใช้ DENGEDEXECUTIONHANDLER { /*** สร้าง <tt> DiscardOldestPolicy </TT> สำหรับผู้ดำเนินการที่กำหนด */ สาธารณะ DiscardOldestPolicy () {} โมฆะสาธารณะปฏิเสธการกำหนด (runnable r, threadpoolexecutor e) {ถ้า (! e.isshutdown ()) {e.getqueue () // ทิ้งงานแรกในคิว e.execute (r); // ดำเนินงานใหม่}}}เมื่องานมาถึงอย่างต่อเนื่องงานจะถูกสำรวจจากคิวและงานใหม่จะถูกดำเนินการ
สรุป
ด้านบนเป็นคำอธิบายโดยละเอียดเกี่ยวกับพูลเธรดของ JDK ที่แนะนำโดยบรรณาธิการ ฉันหวังว่ามันจะเป็นประโยชน์กับทุกคน หากคุณมีคำถามใด ๆ โปรดฝากข้อความถึงฉันและบรรณาธิการจะตอบกลับทุกคนในเวลา ขอบคุณมากสำหรับการสนับสนุนเว็บไซต์ Wulin.com!