พื้นหลังทางเทคนิคของพูลเธรด
ในการเขียนโปรแกรมเชิงวัตถุการสร้างและการทำลายวัตถุนั้นใช้เวลานานเพราะการสร้างวัตถุต้องใช้ทรัพยากรหน่วยความจำหรือทรัพยากรอื่น ๆ นี่คือมากยิ่งขึ้นใน Java ที่เครื่องเสมือนจะพยายามติดตามแต่ละวัตถุเพื่อให้สามารถเก็บขยะได้หลังจากวัตถุถูกทำลาย
ดังนั้นวิธีหนึ่งในการปรับปรุงประสิทธิภาพของโปรแกรมการบริการคือการลดจำนวนเวลาในการสร้างและทำลายวัตถุโดยเฉพาะอย่างยิ่งการสร้างวัตถุที่ใช้ทรัพยากรอย่างมาก วิธีการใช้วัตถุที่มีอยู่เพื่อให้บริการเป็นปัญหาสำคัญที่ต้องแก้ไข ในความเป็นจริงนี่คือเหตุผลที่มีการผลิตเทคโนโลยี "การรวมทรัพยากร" บางอย่าง
ตัวอย่างเช่นส่วนประกอบทั่วไปจำนวนมากที่พบบ่อยใน Android มักจะแยกออกจากแนวคิดของ "พูล" เช่นไลบรารีการโหลดภาพต่างๆและไลบรารีคำขอเครือข่าย แม้ว่ากลไกการส่งข้อความของ Android จะใช้ meaasge.obtain () มันเป็นวัตถุในพูล meaasge ที่ใช้ดังนั้นแนวคิดนี้จึงสำคัญมาก เทคโนโลยีการรวมเธรดที่แนะนำในบทความนี้ยังสอดคล้องกับแนวคิดนี้
ข้อดีของพูลเธรด:
1. การนำเธรดนำกลับมาใช้ใหม่ในพูลเธรดเพื่อลดค่าใช้จ่ายด้านประสิทธิภาพที่เกิดจากการสร้างวัตถุและการทำลายล้าง
2. สามารถควบคุมจำนวนเธรดพร้อมกันสูงสุดได้อย่างมีประสิทธิภาพปรับปรุงการใช้ทรัพยากรของระบบและหลีกเลี่ยงการแข่งขันทรัพยากรที่มากเกินไปและหลีกเลี่ยงการอุดตัน
3. ความสามารถในการจัดการอย่างง่ายหลายเธรดทำให้การใช้เธรดง่ายและมีประสิทธิภาพ
เฟรมเวิร์กเฟรมเวิร์กเธรด
พูลเธรดใน Java ถูกนำไปใช้ผ่านเฟรมเวิร์ก Executor เฟรมเวิร์กผู้บริหารรวมถึงคลาส: ผู้ดำเนินการ, ผู้บริหาร, ExecutorService, ThreadPoolexecutor, Callable และ Future, FutureTask การใช้งาน ฯลฯ
Executor: มีเพียงวิธีเดียวสำหรับอินเทอร์เฟซพูลเธรดทั้งหมด
อินเทอร์เฟซ Public Executor {Void Execute (คำสั่ง Runnable); -ExecutorService: การเพิ่มพฤติกรรมของผู้ดำเนินการเป็นอินเทอร์เฟซโดยตรงที่สุดของคลาสการใช้งาน Executor
ผู้ดำเนินการ: จัดเตรียมชุดของวิธีการโรงงานสำหรับการสร้างพูลเธรดและพูลเธรดที่ส่งคืนทั้งหมดใช้งานส่วนต่อประสาน ExecutorService
Threadpoolexecutor: คลาสการใช้งานเฉพาะของพูลเธรด พูลเธรดต่างๆที่ใช้โดยทั่วไปจะถูกนำไปใช้ตามคลาสนี้ วิธีการก่อสร้างมีดังนี้:
Public Threadpoolexecutor (int corepoolsize, int maximumpoolsize, regalivetime ยาว, หน่วยเวลา, การปิดกั้น <rovnable> workqueue) {this (corepoolsize, maximumpoolsize, keepalivetime, unit, workqueueCorePoolsize: จำนวนเธรดหลักในพูลเธรดและจำนวนเธรดที่ทำงานในพูลเธรดจะไม่เกิน corePoolsize และสามารถอยู่รอดได้โดยค่าเริ่มต้น คุณสามารถตั้งค่าอนุญาตให้ใช้งาน atercorethreadtimeout เป็นจริงจำนวนเธรดหลักคือ 0 และ Keepalivetime ควบคุมเวลาหมดเวลาของเธรดทั้งหมด
Maximumpoolsize: จำนวนเธรดสูงสุดที่อนุญาตโดยพูลเธรด
KEDALIVETIME: หมายถึงเวลาหมดเวลาเมื่อเธรดที่ไม่ได้ใช้งานสิ้นสุดลง
หน่วย: เป็น enum ซึ่งเป็นตัวแทนของหน่วยของ Keepalivetime;
Workqueue: แสดงถึงคิวการปิดกั้น <runnable ที่จัดเก็บงาน
BlockingQueue: BlockingQueue เป็นเครื่องมือที่ใช้เป็นหลักในการควบคุมการซิงโครไนซ์เธรดภายใต้ java.util.concurrent หาก blockqueue ว่างเปล่าการดำเนินการของการดึงบางสิ่งบางอย่างจากการปิดกั้นจะถูกบล็อกและจะไม่ถูกปลุกจนกว่าการปิดกั้นจะเข้าสู่สิ่งนั้น ในทำนองเดียวกันหากการปิดกั้นเต็มรูปแบบการดำเนินการใด ๆ ที่พยายามจัดเก็บสิ่งต่าง ๆ ในนั้นจะถูกบล็อกและจะไม่ถูกปลุกให้ดำเนินการต่อไปจนกว่าจะมีที่ว่างในการปิดกั้น การปิดกั้นคิวมักใช้ในสถานการณ์ของผู้ผลิตและผู้บริโภค ผู้ผลิตเป็นเธรดที่เพิ่มองค์ประกอบในคิวและผู้บริโภคเป็นเธรดที่ใช้องค์ประกอบจากคิว คิวการปิดกั้นคือภาชนะที่ผู้ผลิตเก็บองค์ประกอบและผู้บริโภคจะใช้องค์ประกอบจากภาชนะเท่านั้น คลาสการใช้งานที่เฉพาะเจาะจงรวมถึง LinkedBlockingQueue, Arrayblockingqueued ฯลฯ โดยทั่วไปการบล็อกภายในและการปลุกจะทำได้ผ่านการล็อคและเงื่อนไข (การเรียนรู้และการใช้ล็อคจอแสดงผลและเงื่อนไข)
กระบวนการทำงานของพูลเธรดมีดังนี้:
เมื่อมีการสร้างพูลเธรดเป็นครั้งแรกจะไม่มีด้ายอยู่ข้างใน คิวงานจะถูกส่งผ่านเป็นพารามิเตอร์ อย่างไรก็ตามแม้ว่าจะมีงานในคิวพูลเธรดจะไม่ดำเนินการทันที
เมื่อเพิ่มงานโดยการเรียกใช้วิธีการดำเนินการ () พูลเธรดจะทำการตัดสินต่อไปนี้:
หากจำนวนเธรดที่รันน้อยกว่า corePoolSize ให้สร้างเธรดเพื่อรันงานนี้ทันที
หากจำนวนเธรดที่รันอยู่มากกว่าหรือเท่ากับ corePoolsize ให้ใส่งานนี้ไว้ในคิว
หากคิวเต็มในเวลานี้และจำนวนเธรดที่ทำงานน้อยกว่า maximumpoolsize คุณยังต้องสร้างเธรดที่ไม่ใช่คอร์เพื่อรันงานทันที
หากคิวเต็มและจำนวนเธรดที่รันมากกว่าหรือเท่ากับ maximumpoolsize พูลเธรดจะโยนข้อยกเว้น rejectExecutionException
เมื่อเธรดเสร็จสิ้นงานจะต้องใช้งานถัดไปจากคิวเพื่อดำเนินการ
เมื่อเธรดไม่มีอะไรทำและหลังจากระยะเวลาหนึ่ง (Keepalivetime) พูลเธรดจะตัดสินว่าหากจำนวนเธรดที่ทำงานอยู่ในปัจจุบันมีขนาดใหญ่กว่า corePoolsize แล้วเธรดจะหยุด ดังนั้นหลังจากงานทั้งหมดของพูลเธรดเสร็จสมบูรณ์ในที่สุดมันก็จะลดขนาดของ corepoolsize
การสร้างและการใช้พูลเธรด
พูลเธรดการสร้างใช้วิธีการคงที่ของตัวจัดการคลาสเครื่องมือ ต่อไปนี้เป็นพูลเธรดทั่วไปหลายแห่ง
SingLetHreadExecutor: เธรดพื้นหลังเดี่ยว (คิวบัฟเฟอร์ไม่ได้ จำกัด )
Public ExecutorService NewsingLetHreatHreadExecutor () {ส่งคืน FinalizabledElegatedExecutorService ใหม่ (ใหม่ ThreadPoolexecutor (1, 1, 0L, TimeUnit.Milliseconds, LinkedBlockingQueue ใหม่ <Runnable> ()); -สร้างพูลเธรดเดียว พูลเธรดนี้มีเธรดหลักเดียวที่ใช้งานได้ซึ่งเทียบเท่ากับเธรดเดียวที่ทำงานทั้งหมดในอนุกรม หากเธรดที่ไม่ซ้ำกันนี้สิ้นสุดลงเนื่องจากข้อยกเว้นจะมีเธรดใหม่ที่จะแทนที่ พูลเธรดนี้ทำให้มั่นใจได้ว่าคำสั่งการดำเนินการของงานทั้งหมดจะดำเนินการตามลำดับของการส่งงาน
recidethreadpool: เฉพาะพูลเธรดของเธรดหลักที่มีขนาดคงที่ (คิวบัฟเฟอร์ไม่ จำกัด )
Public ExecutorService newFixedThreadPool (int nthreads) {
ส่งคืน threadpoolexecutor ใหม่ (nthreads, nthreads,
0L, TimeUnit.milliseconds,
ใหม่ LinkedBlockingQueue <runnable> ());
-
สร้างพูลเธรดขนาดคงที่ ทุกครั้งที่มีการส่งงานเธรดจะถูกสร้างขึ้นจนกว่าเธรดจะมีขนาดสูงสุดของพูลเธรด ขนาดพูลเธรดยังคงเหมือนเดิมเมื่อถึงค่าสูงสุด หากเธรดสิ้นสุดลงเนื่องจากข้อยกเว้นการดำเนินการพูลเธรดจะเพิ่มเธรดใหม่
CachedThreadPool: พูลเธรดที่ไม่ได้ จำกัด สามารถทำการรีไซเคิลเธรดอัตโนมัติ
Public ExecutorService newCachedThreadPool () {ส่งคืน ThreadPoolexecutor ใหม่ (0, Integer.max_value, 60L, TimeUnit.seconds, Synchronousqueue ใหม่ <Runnable> ()); -หากขนาดของพูลเธรดเกินกว่าเธรดที่จำเป็นในการประมวลผลงานเธรดที่ไม่ได้ใช้งานบางอย่าง (ไม่มีการดำเนินการใน 60 วินาที) จะถูกรีไซเคิล เมื่อจำนวนงานเพิ่มขึ้นพูลเธรดนี้สามารถเพิ่มเธรดใหม่ได้อย่างชาญฉลาดเพื่อประมวลผลงาน พูลเธรดนี้ไม่ได้ จำกัด ขนาดพูลเธรดซึ่งขึ้นอยู่กับขนาดเธรดสูงสุดที่ระบบปฏิบัติการ (หรือ JVM) สามารถสร้างได้ Synchronousqueue เป็นคิวการปิดกั้นที่มีบัฟเฟอร์ 1
ScheduledThreadPool: พูลเธรดหลักพร้อมพูลเธรดหลักคงที่ขนาดไม่ จำกัด พูลเธรดนี้รองรับความจำเป็นในการทำงานเป็นระยะและเป็นระยะ
Public ExecutorService NewscheduledThreadPool (int corePoolsize) {ส่งคืน scheduledThreadPool ใหม่ (CorePoolsize, Integer.max_value, default_keepalive_millis, milliseconds, delayedworkqueue ใหม่ (); -สร้างพูลเธรดที่ทำงานเป็นระยะ หากไม่ได้ใช้งานพูลเธรดที่ไม่ใช่คอร์จะถูกนำกลับมาใช้ใหม่ภายในเวลา default_keepaliveMillis
มีสองวิธีที่ใช้กันมากที่สุดในการส่งงานในพูลเธรด:
ดำเนินการ:
ExecutorService.Execute (Runnable Runable);
ส่ง:
งาน futureTask = executorService.submit (runnable runnable);
FutureTask <t> task = executorService.submit (runnable runnable, ผลลัพธ์ t);
futureTask <t> task = executoRservice.submit (callable <t> callable);
เช่นเดียวกับการใช้งานการส่ง (เรียกได้ว่าเรียกได้) และใช้กับการส่งเช่นเดียวกับการส่ง (runnable runnable)
สาธารณะ <t> อนาคต <t> ส่ง (callable <t> งาน) {ถ้า (task == null) โยน nullpointerexception ใหม่ (); FutureTask <t> ftask = newTaskfor (งาน); ดำเนินการ (ftask); ส่งคืน ftask;}จะเห็นได้ว่าการส่งเป็นงานที่ส่งคืนผลลัพธ์และจะส่งคืนวัตถุ FutureTask เพื่อให้สามารถรับผลลัพธ์ผ่านวิธี Get () การโทรครั้งสุดท้ายเพื่อส่งยังดำเนินการ (เรียกใช้งานได้) ส่งเฉพาะการห่อหุ้มวัตถุที่เรียกได้หรือรันได้ลงในวัตถุ FutureTask เนื่องจาก FutureTask เป็นสิ่งที่รันได้จึงสามารถดำเนินการได้ในการดำเนินการ สำหรับวัตถุที่เรียกได้และ runnable ถูกห่อหุ้มไว้ในวัตถุ FutureTask ดูที่การใช้ Callable, Future, FutureTask
หลักการของการใช้งานพูลเธรด
หากคุณพูดถึงการใช้พูลเธรดเท่านั้นบล็อกนี้จะไม่มีค่ามาก ที่ดีที่สุดมันเป็นเพียงกระบวนการของการทำความคุ้นเคยกับ API ที่เกี่ยวข้องกับผู้บริหาร กระบวนการใช้งานของพูลเธรดไม่ได้ใช้คำหลักที่ซิงโครไนซ์ แต่ใช้คิวที่มีความผันผวนล็อคและซิงโครนัส (บล็อก) คลาสที่เกี่ยวข้องกับอะตอม, FutureTask ฯลฯ เนื่องจากหลังมีประสิทธิภาพที่ดีขึ้น กระบวนการทำความเข้าใจสามารถเรียนรู้แนวคิดของการควบคุมที่เกิดขึ้นพร้อมกันในซอร์สโค้ดได้ดี
ข้อดีของการรวมเกลียวที่กล่าวถึงในตอนแรกสรุปได้ดังนี้:
นำกลับมาใช้ซ้ำ
ควบคุมจำนวนสูงสุดของการเกิดขึ้นพร้อมกัน
จัดการเธรด
1. กระบวนการมัลติเพล็กซ์เธรด
เพื่อทำความเข้าใจหลักการของเธรดมัลติเพล็กซ์คุณควรเข้าใจวัฏจักรชีวิตของเธรดก่อน
ในช่วงวงจรชีวิตของเธรดมันต้องผ่านห้ารัฐ: ใหม่, วิ่งได้, วิ่ง, ถูกบล็อกและตาย
เธรดสร้างเธรดใหม่ผ่านใหม่ กระบวนการนี้คือการเริ่มต้นข้อมูลเธรดบางอย่างเช่นชื่อเธรด, ID, กลุ่มที่เธรดเป็น ฯลฯ ซึ่งถือได้ว่าเป็นเพียงวัตถุธรรมดา หลังจากเรียกเธรดของ Start () เครื่องเสมือน Java จะสร้างสแต็กการเรียกใช้วิธีและตัวนับโปรแกรมสำหรับมันและในขณะเดียวกันก็เริ่มต้นเป็นจริงและจากนั้นจะมีข้อยกเว้นเมื่อเรียกวิธีการเริ่มต้น
เธรดในสถานะนี้ไม่ได้เริ่มทำงาน แต่หมายความว่าเธรดสามารถรันได้เท่านั้น สำหรับเมื่อเธรดเริ่มทำงานขึ้นอยู่กับตัวกำหนดตารางเวลาใน JVM เมื่อเธรดได้รับ CPU วิธีการเรียกใช้ () จะถูกเรียก อย่าเรียกวิธีการ Run () ด้วยตัวคุณเอง จากนั้นสลับระหว่างการปิดกั้นแบบเร่ร่อนตามการกำหนดเวลา CPU จนกว่าวิธีการเรียกใช้ () จะสิ้นสุดลงหรือวิธีอื่น ๆ หยุดเธรดและป้อนสถานะตาย
ดังนั้นหลักการของการใช้เธรดการใช้ซ้ำควรทำให้เธรดมีชีวิตอยู่ (พร้อมวิ่งหรือปิดกั้น) ถัดไปลองมาดูกันว่า ThreadPoolexecutor ใช้การใช้เธรดซ้ำอย่างไร
คลาสคนงานหลักใน ThreadPoolexecutor ควบคุมการใช้เธรดซ้ำ ดูรหัสที่เรียบง่ายของคลาสคนงานดังนั้นจึงเข้าใจง่าย:
ผู้ปฏิบัติงานในชั้นเรียนสุดท้ายส่วนตัวใช้ Runnable {เธรดสุดท้าย; runnable firsttask; คนงาน (runnable firsttask) {this.firsttask = firsttask; this.thread = getThreadFactory (). newThread (this);} public void run () {runworker W.FirstTask; W.FirstTask = null; ในขณะที่ (งาน! = null || (task = getTask ())! = null) {task.run ();}}}คนงานเป็นคนที่รันได้และมีเธรดในเวลาเดียวกัน เธรดนี้เป็นเธรดที่จะเปิด เมื่อสร้างวัตถุผู้ปฏิบัติงานใหม่วัตถุเธรดใหม่จะถูกสร้างขึ้นในเวลาเดียวกันและคนงานจะถูกส่งผ่านไปยัง tthread เป็นพารามิเตอร์ ด้วยวิธีนี้เมื่อมีการเรียกวิธีการเริ่มต้นของเธรดเมธอด Run () ของคนงานกำลังทำงานจริง จากนั้นใน runworker () มีการวนซ้ำในขณะที่ทำให้ได้รับวัตถุที่เรียกใช้จาก getTask () และดำเนินการตามลำดับ GetTask () รับวัตถุที่รันได้อย่างไร
ยังคงเป็นรหัสที่เรียบง่าย:
private runnable getTask () {ถ้า (บางกรณีพิเศษ) {return null; } runnable r = workqueue.take (); return r;}Workqueue นี้เป็นคิวการปิดกั้นที่เก็บงานเมื่อเริ่มต้น ThreadPoolexecutor คิวเก็บงานที่รันได้ที่จะดำเนินการ เนื่องจาก BlockingQueue เป็นคิวการปิดกั้นการปิดกั้นการใช้งาน () จะว่างเปล่าและเข้าสู่สถานะการรอคอยจนกว่าจะมีการเพิ่มวัตถุใหม่ในการปิดกั้นเพื่อปลุกเธรดที่ถูกบล็อก ดังนั้นโดยทั่วไปวิธีการ RUN () ของเธรดจะไม่สิ้นสุด แต่จะดำเนินการต่อไปเพื่อดำเนินงานที่รันได้จาก Workqueue ซึ่งบรรลุหลักการของการใช้เธรดซ้ำ
2. ควบคุมจำนวนสูงสุดของการเกิดขึ้นพร้อมกัน
ดังนั้นเมื่อใดที่ Runnable ใส่เข้าไปใน Workqueue? คนงานถูกสร้างขึ้นเมื่อใด เธรดในคนงานเรียกว่า Start () เมื่อใดเพื่อเปิดเธรดใหม่เพื่อเรียกใช้วิธีการทำงานของ Worker Run ()? การวิเคราะห์ข้างต้นแสดงให้เห็นว่า runworker () ในคนงานทำงานหนึ่งงานต่อไปอีกอย่างหนึ่งตามลำดับดังนั้นการเกิดขึ้นพร้อมกันจะปรากฏตัวอย่างไร
เป็นเรื่องง่ายที่จะคิดว่าคุณจะทำภารกิจข้างต้นบางอย่างเมื่อคุณดำเนินการ (Runnable Runnable) มาดูกันว่ามันทำอย่างไรในการดำเนินการ
ดำเนินการ:
รหัสง่าย
โมฆะสาธารณะดำเนินการ (คำสั่ง runnable) {if (command == null) โยน nullpointerexception ใหม่ (); int c = ctl.get (); // จำนวนเธรดปัจจุบัน <corePoolSizeif (workerCountof (c) <corePoolSize) {// เริ่มเธรดใหม่โดยตรง if (addworker (คำสั่ง, true)) return; c = ctl.get ();} // จำนวนเธรดที่ใช้งานอยู่> = corePoolsize // runstate กำลังทำงาน && คิวไม่เต็มถ้า (c) && workqueue.offer (คำสั่ง)) if (! isrunning (re-recheck) && ลบ (คำสั่ง)) ปฏิเสธ (คำสั่ง); // ใช้กลยุทธ์ที่ระบุโดยพูลเธรดเพื่อปฏิเสธงาน // สองกรณี: // 1. สถานะที่ไม่รันนิ่งปฏิเสธงานใหม่ // 2. undwork)addworker:
รหัสง่าย
Addworker บูลีนส่วนตัว (runnable firsttask, boolean core) {int wc = workerCountof (c); ถ้า (wc> = (core? corepoolsize: maximumpoolsize)) {return false;} w = คนงานใหม่ตามรหัสให้ดูที่สถานการณ์ที่กล่าวถึงข้างต้นของการเพิ่มงานระหว่างงานพูลเธรด:
* หากจำนวนเธรดที่รันน้อยกว่า corePoolSize ให้สร้างเธรดเพื่อเรียกใช้งานนี้ทันที
* หากจำนวนเธรดที่รันมากกว่าหรือเท่ากับ corePoolsize ให้ใส่งานนี้ไว้ในคิว
* หากคิวเต็มในเวลานี้และจำนวนเธรดที่ทำงานน้อยกว่า maximumpoolsize คุณยังต้องสร้างเธรดที่ไม่ใช่คอร์เพื่อรันงานทันที
* หากคิวเต็มและจำนวนเธรดที่รันมากกว่าหรือเท่ากับ maximumpoolsize พูลเธรดจะโยนข้อยกเว้น rejectExecutionException
นี่คือเหตุผลที่ asynctask ของ Android ถูกดำเนินการในแบบคู่ขนานและเกินจำนวนงานสูงสุดและโยน RejectExecutionException สำหรับรายละเอียดโปรดดูที่การตีความซอร์สโค้ด Asynctask เวอร์ชันล่าสุดและด้านมืดของ Asynctask
หากเธรดใหม่ถูกสร้างขึ้นสำเร็จผ่าน addworker ให้เริ่ม () และใช้ FirstTask เป็นงานแรกที่ดำเนินการใน Run () ในคนงานนี้
แม้ว่างานของคนงานแต่ละคนคือการประมวลผลแบบอนุกรมหากมีการสร้างคนงานหลายคนเพราะพวกเขาแบ่งปันการทำงานพวกเขาจะถูกประมวลผลแบบขนาน
ดังนั้นหมายเลขพร้อมกันสูงสุดจึงถูกควบคุมตาม corepoolsize และ maximumpoolsize กระบวนการทั่วไปสามารถแสดงได้ด้วยรูปด้านล่าง
คำอธิบายและรูปภาพข้างต้นสามารถเข้าใจได้ดี
หากคุณมีส่วนร่วมในการพัฒนา Android และคุ้นเคยกับหลักการของ Handler คุณอาจคิดว่าภาพนี้ค่อนข้างคุ้นเคย กระบวนการบางอย่างคล้ายกับที่ใช้โดย Handler, Looper และ Meaasge handler.send (ข้อความ) เทียบเท่ากับการดำเนินการ (runnuble) คิว meaasge ที่เก็บรักษาไว้ใน looper นั้นเทียบเท่ากับการปิดกั้น อย่างไรก็ตามคุณต้องรักษาคิวนี้โดยการซิงโครไนซ์ ฟังก์ชั่น loop () ในลูปลูปเพื่อใช้ meaasge จากคิว meaasge และ runwork () ในคนงานอย่างต่อเนื่องได้รับการวิ่งจาก Blockingqueue
3. จัดการเธรด
ผ่านพูลเธรดเราสามารถจัดการการนำเธรดมาใช้ใหม่ควบคุมหมายเลขพร้อมกันและทำลายกระบวนการ การใช้ซ้ำของเธรดและการควบคุมพร้อมกันได้รับการกล่าวถึงข้างต้นและกระบวนการจัดการเธรดได้ถูกสลับเข้าด้วยกันซึ่งเป็นเรื่องง่ายที่จะเข้าใจ
มีตัวแปร CTL Atomicinteger ใน ThreadPoolexecutor สองเนื้อหาจะถูกบันทึกผ่านตัวแปรนี้:
จำนวนเธรดทั้งหมด แต่ละเธรดอยู่ในสถานะที่เก็บเธรด 29 บิตที่ต่ำกว่าและเก็บ runstate 3 บิตที่สูงขึ้น ค่าที่แตกต่างกันนั้นได้มาจากการดำเนินการบิต
Private Atomicinteger CTL = ใหม่ atomicinteger (ctlof (วิ่ง, 0)); // รับสถานะของกระทู้ส่วนตัวคงที่ int int int c) {return c & ~ ความจุ;} // รับจำนวนพนักงานส่วนตัว ความจุ;} // คำว่าเธรดกำลังใช้บูลีนคงที่ส่วนตัว isrunning (int c) {return c <shutdown;}ที่นี่กระบวนการปิดการปิดพูลเธรดส่วนใหญ่วิเคราะห์โดยการปิดและ shutdownnow () ก่อนอื่นพูลเธรดมีห้าสถานะในการควบคุมการเพิ่มงานและการดำเนินการ มีการแนะนำสามประเภทหลักต่อไปนี้:
สถานะการรัน: พูลเธรดทำงานตามปกติและสามารถรับงานใหม่และงานกระบวนการในคิว;
สถานะการปิดระบบ: ไม่ยอมรับงานใหม่ แต่งานในคิวจะถูกดำเนินการ;
สถานะหยุด: ไม่ยอมรับงานใหม่อีกต่อไปและการปิดงานจะไม่ถูกประมวลผลในคิว วิธีนี้จะตั้งค่า runstate เป็นปิดและจะยุติเธรดที่ไม่ได้ใช้งานทั้งหมดในขณะที่เธรดที่ยังคงทำงานไม่ได้รับผลกระทบดังนั้นบุคคลงานในคิวจะถูกดำเนินการ
เมธอด shutdownnow ตั้งค่า runstate ให้หยุด ความแตกต่างระหว่างวิธีการปิดระบบวิธีนี้จะยุติเธรดทั้งหมดดังนั้นงานในคิวจะไม่ถูกดำเนินการ
สรุป: ผ่านการวิเคราะห์ซอร์สโค้ด ThreadPoolexecutor เรามีความเข้าใจทั่วไปเกี่ยวกับกระบวนการสร้างพูลเธรดเพิ่มงานและดำเนินการพูลเธรด หากคุณคุ้นเคยกับกระบวนการเหล่านี้มันจะง่ายกว่าที่จะใช้พูลเธรด
การควบคุมพร้อมกันบางส่วนได้เรียนรู้จากมันและการใช้งานการประมวลผลงานของแบบจำลองผู้ผลิต-ผู้บริโภคจะช่วยให้เข้าใจหรือแก้ปัญหาอื่น ๆ ที่เกี่ยวข้องอื่น ๆ ในอนาคต ตัวอย่างเช่นกลไกตัวจัดการใน Android และคิว Messager ใน Looper ก็โอเคที่จะใช้ Blookqueue เพื่อจัดการกับมัน นี่คือกำไรจากการอ่านซอร์สโค้ด
ข้างต้นคือข้อมูลที่แยกพูลเธรด Java เราจะยังคงเพิ่มข้อมูลที่เกี่ยวข้องในอนาคต ขอบคุณสำหรับการสนับสนุนเว็บไซต์นี้!