เริ่มต้นใน Java 5 Java จัดหาพูลเธรดของตัวเอง พูลเธรดเป็นคอนเทนเนอร์เธรดซึ่งจะดำเนินการจำนวนเธรดที่ได้รับการจัดอันดับเท่านั้น java.util.concurrent.threadpoolexecutor เป็นพูลเธรด มันมีความยืดหยุ่นมาก แต่ก็มีความซับซ้อนในการใช้ดังนั้นบทความนี้จะแนะนำ
อันดับแรกคือตัวสร้าง นำตัวสร้างที่ง่ายที่สุดเป็นตัวอย่าง:
Public Threadpoolexecutor (int corepoolsize, int maximumpoolsize, regalivetime ยาว, หน่วย TimeUnit, BlockingQueue <Runnable> Workqueue)
มันดูค่อนข้างซับซ้อน ให้ฉันแนะนำที่นี่
CorePoolsize หมายถึงขนาดพูลเธรดที่สงวนไว้
Maximumpoolsize หมายถึงขนาดสูงสุดของพูลเธรด
Keepalivetime หมายถึงเวลาหมดเวลาเมื่อเธรดที่ไม่ได้ใช้งานสิ้นสุดลง
หน่วยคือการแจงนับที่เป็นตัวแทนของหน่วยของ Keepalivetime
Workqueue แสดงถึงคิวสำหรับการจัดเก็บงาน
เราสามารถเข้าใจความสำคัญของพารามิเตอร์เหล่านี้จากกระบวนการทำงานของพูลเธรด กระบวนการทำงานของพูลเธรดมีดังนี้:
1. เมื่อมีการสร้างพูลเธรดเป็นครั้งแรกจะไม่มีเธรดอยู่ข้างใน คิวงานจะถูกส่งผ่านเป็นพารามิเตอร์ อย่างไรก็ตามแม้ว่าจะมีงานในคิวพูลเธรดจะไม่ดำเนินการทันที
2. เมื่อโทรหาวิธีการ () เพื่อเพิ่มงานพูลเธรดจะทำการตัดสินต่อไปนี้:
.
b
c
D
3. เมื่อเธรดเสร็จสิ้นงานจะต้องใช้งานจากคิวเพื่อดำเนินการ
4. เมื่อเธรดไม่มีอะไรทำและใช้เวลาระยะเวลาหนึ่ง (Keepalivetime) พูลเธรดจะตัดสินว่าหากจำนวนเธรดที่ทำงานอยู่ในปัจจุบันมีขนาดใหญ่กว่า corePoolsize แล้วเธรดจะหยุด ดังนั้นหลังจากงานทั้งหมดของพูลเธรดเสร็จสมบูรณ์ในที่สุดมันก็จะลดขนาดของ corepoolsize
กระบวนการนี้แสดงให้เห็นว่าไม่จำเป็นต้องดำเนินงานก่อนหากคุณเข้าร่วมงานก่อน สมมติว่าขนาดคิวคือ 10, corepoolsize คือ 3 และ maximumpoolsize คือ 6 จากนั้นเมื่อเพิ่ม 20 งานคำสั่งการดำเนินการมีดังนี้: ก่อนงาน 1, 2, 3 ถูกดำเนินการแล้วงาน 4 ~ 13 จะถูกวางไว้ ในคิว ในเวลานี้คิวเต็มงาน 14, 15, 16 จะถูกดำเนินการทันทีและงาน 17 ~ 20 จะโยนข้อยกเว้น คำสั่งสุดท้ายคือ: 1, 2, 3, 14, 15, 16, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 นี่คือตัวอย่างของการใช้พูลเธรด:
โมฆะสาธารณะคงที่หลัก (สตริง [] args) {blockingqueue <runnable> queue = ใหม่ linkedblockingqueue <runnable> (); 0; i <20; Out.
คำอธิบายของตัวอย่างนี้มีดังนี้:
1. BlockingQueue เป็นเพียงอินเทอร์เฟซ ข้อดีของการใช้ LinkedBlockingQueue คือไม่มีขีด จำกัด ขนาด ด้วยวิธีนี้เนื่องจากคิวจะไม่เต็ม, Execute () จะไม่โยนข้อยกเว้นและจำนวนเธรดที่ทำงานในพูลเธรดจะไม่เกิน corePoolsize ดังนั้นพารามิเตอร์ keepalivetime จึงไม่มีความหมาย
2. วิธีการปิด () จะไม่บล็อก หลังจากเรียกใช้วิธีการปิด () เธรดหลักจะสิ้นสุดลงทันทีและพูลเธรดจะทำงานต่อไปจนกว่างานทั้งหมดจะถูกดำเนินการก่อนที่จะหยุด หากไม่เรียกวิธีการปิด () พูลเธรดจะยังคงอยู่เพื่อให้สามารถเพิ่มงานใหม่ได้ตลอดเวลา
ณ จุดนี้ฉันได้แนะนำเพียงส่วนเล็ก ๆ ของพูลเธรดนี้ Threadpoolexecutor สามารถปรับขนาดได้มาก แต่หลักฐานของการขยายมันจะคุ้นเคยกับวิธีการทำงาน บทความต่อไปนี้จะอธิบายวิธีการขยายคลาส Threadpoolexecutor
คลาส ava.util.concurrent.threadpoolexecutor ให้การขยายความสามารถที่หลากหลาย คุณสามารถปรับแต่งพฤติกรรมโดยการสร้างคลาสย่อย ตัวอย่างเช่นฉันต้องการพิมพ์ข้อความหลังจากแต่ละงานจบ แต่ฉันไม่สามารถแก้ไขวัตถุงานได้จากนั้นฉันสามารถเขียนสิ่งนี้:
threadpoolexecutor executor = ใหม่ threadpoolexecutor (ขนาด, maxsize, 1, timeunit.days, คิว) {@Override ป้องกันโมฆะ AfterExecute (Runnable R, t hrowable t) {system.out.out.println ("งานเสร็จ");
นอกเหนือจากวิธี Athexecute แล้วคลาส Threadpoolexecutor ยังมีวิธีการ beforeExecute () และ terminated () ที่สามารถแทนที่ซึ่งจะถูกดำเนินการก่อนที่งานจะถูกดำเนินการและหลังจากพูลเธรดทั้งหมดหยุดลง
นอกเหนือจากการเพิ่มการกระทำก่อนและหลังงานแล้ว ThreadPoolexecutor ยังช่วยให้คุณสามารถปรับแต่งนโยบายการดำเนินการหลังจากการเพิ่มงานล้มเหลว คุณสามารถเรียกเมธอด setrejectedExecutionHandler () ของพูลเธรดและแทนที่นโยบายที่มีอยู่ด้วยวัตถุที่ถูกปฏิเสธการกำหนดค่าใช้จ่ายที่กำหนดเอง ThreadPoolexecutor มีนโยบายที่มีอยู่ 4 ฉบับคือ:
threadpoolexecutor.abortpolicy: ระบุว่างานถูกปฏิเสธและมีข้อยกเว้นถูกโยนทิ้งไป
threadpoolexecutor.discardpolicy: หมายถึงการปฏิเสธงาน แต่ไม่ได้ดำเนินการใด ๆ
Threadpoolexecutor.CallerRunspolicy: ระบุว่างานถูกปฏิเสธและงานจะถูกดำเนินการโดยตรงในเธรดของผู้โทร
Threadpoolexecutor.discardoldestpolicy: หมายความว่างานแรกในคิวงานจะถูกยกเลิกก่อนจากนั้นงานจะถูกเพิ่มเข้าไปในคิว
นี่คือตัวอย่าง:
threadpoolexecutor executor = ใหม่ threadpoolexecutor (ขนาด, maxsize, 1, timeunit.days, คิว);
Executor.SetRejectedExecutionHandler (ใหม่ threadpoolexecutor.discardpolicy ());
นอกจากนี้คุณยังสามารถเขียนนโยบายของคุณเองได้โดยใช้อินเตอร์เฟส DensedExecutionHandler นี่คือตัวอย่าง:
threadpoolexecutor executor = new Threadpoolexecutor (3, 6, 1, TimeUnit.seconds, คิว, New DempedExecutionHandler () {โมฆะสาธารณะปฏิเสธการเปิดใช้งาน . ", r.hashcode ()));}});