คำนำ
ในการเขียนโปรแกรมแบบมัลติเธรดมันไม่สมจริงที่จะกำหนดเธรดให้กับแต่ละงานและค่าใช้จ่ายและการใช้ทรัพยากรของการสร้างเธรดนั้นสูงมาก พูลเธรดเข้ามาเป็นเครื่องมือที่ทรงพลังสำหรับเราในการจัดการเธรด ผ่านอินเทอร์เฟซผู้บริหาร Java จัดเตรียมวิธีมาตรฐานในการแยกกระบวนการส่งงานและดำเนินการตามกระบวนการและใช้ Runnable เพื่อเป็นตัวแทนของงาน
ถัดไปให้วิเคราะห์การใช้งานของ Java Thread Pool Framework Threadpoolexecutor
การวิเคราะห์ต่อไปนี้ขึ้นอยู่กับ JDK1.7
วงจรชีวิต
ใน Threadpoolexecutor ความจุ 3 บิตบนจะใช้เพื่อแสดงสถานะการทำงานซึ่งก็คือ:
1.Running: รับงานใหม่และงานกระบวนการในคิวงาน
2. Shutdown: งานที่ไม่ได้รับงานใหม่ แต่จัดการคิวงาน
3. Stop: ไม่ได้รับงานใหม่ไม่มีการปล่อยคิวงานและงานทั้งหมดที่กำลังดำเนินการถูกขัดจังหวะในเวลาเดียวกัน
4.Tidying: งานทั้งหมดถูกยกเลิกจำนวนเธรดคนงานคือ 0 เมื่อถึงสถานะนี้จะถูกยกเลิก () จะถูกดำเนินการ
5.Minated: ถูกยกเลิก () ถูกดำเนินการแล้ว
แผนภาพการเปลี่ยนแปลงของรัฐ
คลาสอะตอมใช้เพื่อแสดงถึงสถานะของสถานะใน Threadpoolexecutor
Private Final Atomicinteger CTL = ใหม่ Atomicinteger (CTLOF (Running, 0));
โมเดลพูลเธรด
พารามิเตอร์หลัก
CorePoolSize: จำนวนขั้นต่ำของเธรดผู้ปฏิบัติงานที่มีชีวิต (หากตั้งค่า allycorethreadtimeOut แล้วค่านี้คือ 0)
Maximumpoolsize: จำนวนเธรดสูงสุด จำกัด โดยความจุ
Keepalivetime: เวลาการอยู่รอดของเธรดที่เกี่ยวข้องหน่วยเวลาจะถูกระบุโดย TimeUnit
Workqueue: คิวงานจัดเก็บงานที่จะดำเนินการ
RejectExecutionHandler: นโยบายการปฏิเสธความจุสูงสุดของพูลเธรดจะถูกเรียกใช้หลังจากพูลเธรดเต็ม: สามบิตแรกในความจุถูกใช้เป็นบิตธงนั่นคือความจุสูงสุดของเธรดคนงานคือ (2^29) -1 -1) -1 -1
สี่รุ่น
Cachedthreadpool: พูลเธรดที่แคช หากขนาดปัจจุบันของพูลเธรดเกินข้อกำหนดการประมวลผลเธรดที่ไม่ได้ใช้งานจะถูกนำกลับมาใช้ใหม่ เมื่อความต้องการเพิ่มขึ้นเธรดใหม่สามารถเพิ่มได้ ไม่มีการ จำกัด ขนาดของพูลเธรด
recidethreadpool: พูลเธรดขนาดคงที่ เมื่อส่งงานเธรดจะถูกสร้างขึ้นจนกว่าจะถึงจำนวนพูลเธรดสูงสุด ในเวลานี้ขนาดของพูลเธรดจะไม่เปลี่ยนแปลงอีกต่อไป
SingLetHreadPool: พูลเธรดเดี่ยวซึ่งมีเธรดคนงานเพียงคนเดียวในการทำงาน สามารถมั่นใจได้ว่างานจะถูกดำเนินการตามลำดับตามลำดับที่อยู่ในคิว หากเธรดนี้สิ้นสุดอย่างผิดปกติเธรดใหม่จะถูกสร้างขึ้นเพื่อดำเนินการงาน
ScheduledThreadPool: พูลเธรดขนาดคงที่และทำงานในลักษณะล่าช้าหรือกำหนดเวลาคล้ายกับตัวจับเวลา
ดำเนินการงาน
ตรรกะหลัก:
1. จำนวนเธรดปัจจุบัน <corepoolsize เปิดเธรดหลักใหม่โดยตรงเพื่อเรียกใช้งาน addworker งาน (คำสั่ง, จริง)
2. จำนวนเธรดปัจจุบัน> = corepoolsize และงานจะถูกเพิ่มเข้ากับคิวงานสำเร็จ
1). ตรวจสอบว่าสถานะปัจจุบันของพูลเธรดกำลังทำงานอยู่หรือไม่
2). ถ้าไม่งานจะถูกปฏิเสธ
3). ถ้าเป็นเช่นนั้นให้ตรวจสอบว่าจำนวนเธรดปัจจุบันคือ 0 ถ้าเป็น 0 หรือไม่เพิ่มเธรดคนงาน
3. เปิดงานการดำเนินการเธรดปกติ addworker (คำสั่ง, เท็จ) และปฏิเสธงานหากไม่สามารถเริ่มต้นได้ จากการวิเคราะห์ข้างต้นเราสามารถสรุปการทำงานของสระว่ายน้ำสี่ขั้นตอน:
1) .poolsize <corepoolsize และคิวว่างเปล่า เธรดใหม่จะถูกสร้างขึ้นเพื่อประมวลผลงานที่ส่ง
2) .PoolSize == CorePoolSize ในเวลานี้งานที่ส่งเข้าสู่คิวงาน เธรดคนงานจะได้รับการดำเนินงานจากคิว ในเวลานี้คิวไม่ว่างเปล่าและไม่เต็ม
3) .PoolSize == CorePoolSize และคิวเต็ม เธรดใหม่จะถูกสร้างขึ้นเพื่อประมวลผลงานที่ส่ง แต่ poolsize <maxpoolsize
4) .PoolSize == MaxPoolSize และคิวเต็มรูปแบบนโยบายการปฏิเสธจะถูกเรียกใช้
นโยบายการปฏิเสธ <br /> เราพูดถึงก่อนหน้านี้ว่าหากงานไม่สามารถดำเนินการได้ก็จะถูกปฏิเสธ DensedExecutionHandler เป็นอินเทอร์เฟซสำหรับการจัดการงานที่ถูกปฏิเสธ นี่คือกลยุทธ์การปฏิเสธสี่ประการ
Abortpolicy: นโยบายเริ่มต้น, เลิกงาน, โยนปฏิเสธการรับรู้
Callerrunspolicy: ดำเนินงานปัจจุบันในเธรดผู้โทรโดยไม่ต้องโยนข้อยกเว้น
DiscardPolicy: ยกเลิกนโยบายทิ้งงานโดยตรงและอย่าโยนข้อยกเว้น
di scandolderspolicy: ละทิ้งงานที่เก่าแก่ที่สุดดำเนินงานปัจจุบันและอย่าโยนข้อยกเว้น
คนงานในพูลเธรด
คนงานสืบทอด AbstractqueuedSynchronizer และ Runnable อดีตให้ฟังก์ชั่นการล็อคคนงานและหลังดำเนินการวิธีหลักของเธรดคนงาน runworker (คนงาน W) (SNAP Task Execution จากคิวงาน) การอ้างอิงของคนงานพบได้ในคอลเลกชันคนงานและได้รับการคุ้มครองโดย Mainlock
Private Final Reentrantlock mainlock = ใหม่ reentrantlock ();
HashSet สุดท้ายส่วนตัว <Worker> คนงาน = new HashSet <Worker> ();
ฟังก์ชั่นหลัก runworker
ต่อไปนี้เป็นตรรกะที่เรียบง่ายหมายเหตุ: การเรียกใช้ของแต่ละเธรดคนงานแต่ละคนดำเนินการฟังก์ชั่นต่อไปนี้
void runworker สุดท้าย (คนงาน w) {เธรด wt = thread.currentthread (); task runnable = w.firsttask; W.FirstTask = NULL; ในขณะที่ (งาน! = null || (task = getTask ())! = null) {w.lock (); beforeexecute (wt, task); task.run (); AfterExecute (งานโยน); W.Unlock (); } processworkerExit (w, เสร็จสิ้นอย่างต่อเนื่อง);} 1. รับงานจาก GetTask ()
2. ล็อคคนงาน
3. ดำเนินการ beforeexecute (wt, task) ซึ่งเป็นวิธีการขยายที่จัดทำโดย threadpoolexecutor เป็น subclasses
4. เรียกใช้งาน หากผู้ปฏิบัติงานได้กำหนดค่างานแรกงานแรกจะถูกดำเนินการก่อนและเพียงครั้งเดียว
5. ดำเนินการ Athexecute (งานโยน);
6. ปลดล็อกคนงาน
7. หากงานที่ได้รับเป็นโมฆะให้ปิดคนงาน
รับงาน getTask
คิวงานภายในสระว่ายน้ำเป็นคิวการปิดกั้นซึ่งผ่านเข้ามาในระหว่างการก่อสร้าง
การปิดกั้นครั้งสุดท้ายส่วนตัว <Runnable> Workqueue;
getTask () ได้รับงานจากคิวงานรองรับการปิดกั้นและการรอการหมดเวลารองาน สี่สถานการณ์จะทำให้เป็นโมฆะและคนงานถูกปิด
1. จำนวนเธรดที่มีอยู่เกินจำนวนเธรดสูงสุด
2. พูลเธรดอยู่ในสถานะหยุด
3. พูลเธรดอยู่ในสถานะปิดระบบและคิวงานว่างเปล่า
4. การหมดเวลาการทำงานของเธรดและจำนวนเธรดเกินจำนวนเธรดที่เก็บไว้
Core Logic: หมดเวลาหรือปิดกั้นงานที่รอคอยในคิวการบล็อก งานที่รอกำหนดเวลาจะทำให้เธรดคนงานถูกปิด
timed = allowcorethreadtimeout || wc> corepoolsize; runnable r = หมดเวลา? workqueue.poll (keepalivetime, timeunit.nanoseconds): workqueue.take ();
การรองานจะหมดเวลาในสองกรณี:
1. อนุญาตให้เธรดหลักรอการหมดเวลานั่นคืออนุญาตให้ใช้งานได้ง่าย (จริง)
2. เธรดปัจจุบันเป็นเธรดปกติในเวลานี้ wc> corepoolsize
คิวงานใช้ BlockingQueue ดังนั้นฉันจะไม่ขยายที่นี่ ฉันจะเขียนการวิเคราะห์โดยละเอียดในภายหลัง
สรุป
Threadpoolexecutor ขึ้นอยู่กับรุ่นผู้ผลิต-ผู้บริโภค การดำเนินงานของการส่งงานนั้นเทียบเท่ากับผู้ผลิตและเธรดของการดำเนินงานนั้นเทียบเท่ากับผู้บริโภค
Executors มีวิธีการสี่วิธีในการสร้างโมเดลพูลเธรดตาม ThreadPoolexecutor นอกจากนี้เราสามารถสืบทอด threadpoolexecutor โดยตรงและเขียนใหม่ beforeexecute และ methodexecute เพื่อปรับแต่งกระบวนการดำเนินการงานของพูลเธรด
การใช้คิวที่มีขอบเขตหรือคิวที่ไม่มีขอบเขตจะต้องได้รับการพิจารณาตามสถานการณ์ที่เฉพาะเจาะจงและขนาดของคิวงานและจำนวนเธรดจะต้องได้รับการพิจารณาอย่างรอบคอบ
แนะนำให้ใช้นโยบายการปฏิเสธเพื่อใช้ Callerrunspolicy ซึ่งไม่ละทิ้งงานหรือโยนข้อยกเว้น แต่แทนที่จะทิ้งงานไปยังเธรดผู้โทรเพื่อดำเนินการ
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น