บทความนี้วิเคราะห์การใช้พูลเธรด Java สี่รายการสำหรับการอ้างอิงของคุณ เนื้อหาเฉพาะมีดังนี้
1. ข้อเสียของเธรดใหม่
คุณยังคงทำเธรดใหม่ดังนี้เมื่อดำเนินงานแบบอะซิงโครนัสหรือไม่?
เธรดใหม่ (ใหม่ runnable () {@Override โมฆะสาธารณะ run () {// วิธีการที่สร้างอัตโนมัติ todo stub}}) เริ่มต้น ();ถ้าอย่างนั้นคุณจะมีความลึกมากเกินไปข้อเสียของเธรดใหม่มีดังนี้:
. ประสิทธิภาพของเธรดใหม่ไม่ดีทุกครั้ง
ข. เธรดขาดการจัดการแบบครบวงจรซึ่งอาจสร้างเธรดใหม่โดยไม่มีข้อ จำกัด แข่งขันกันและอาจใช้ทรัพยากรระบบมากเกินไปที่จะทำให้เกิดการล่มหรือ ooms
ค. การขาดฟังก์ชั่นเพิ่มเติมเช่นการดำเนินการตามกำหนดเวลาการดำเนินการเป็นระยะการหยุดชะงักของเธรด
เมื่อเทียบกับเธรดใหม่ข้อดีของพูลเธรดทั้งสี่ที่จัดทำโดย Java คือ:
. นำเธรดที่มีอยู่กลับมาใช้ใหม่เพื่อลดค่าใช้จ่ายของการสร้างวัตถุและการสูญพันธุ์และทำงานได้ดี
ข. มันสามารถควบคุมจำนวนมากที่สุดของเธรดที่เกิดขึ้นพร้อมกันปรับปรุงอัตราการใช้ประโยชน์ของทรัพยากรระบบและหลีกเลี่ยงการแข่งขันทรัพยากรที่มากเกินไปและหลีกเลี่ยงการอุดตัน
ค. จัดเตรียมฟังก์ชั่นเช่นการดำเนินการตามกำหนดเวลาการดำเนินการปกติเธรดเดี่ยวการควบคุมหมายเลขพร้อมกัน ฯลฯ
2. พูลเธรด Java
Java จัดหาพูลเธรดสี่ประเภทผ่านผู้บริหารคือ:
Newcachedthreadpool สร้างพูลเธรดที่แคช หากความยาวของพูลเธรดเกินความต้องการการประมวลผลจะสามารถรีไซเคิลเธรดที่ไม่ได้ใช้งานได้อย่างยืดหยุ่น หากไม่มีการรีไซเคิลให้สร้างเธรดใหม่
Newfixedthreadpool สร้างพูลเธรดที่มีความยาวคงที่ซึ่งสามารถควบคุมจำนวนเธรดสูงสุดพร้อมกันและเธรดส่วนเกินจะรอในคิว
NewscheduledThreadPool สร้างพูลเธรดที่มีความยาวคงที่ซึ่งรองรับการดำเนินงานตามเวลาและเป็นระยะ
NewsingLetHreadExecutor สร้างพูลเธรดเดี่ยวซึ่งจะใช้เธรดคนงานที่ไม่ซ้ำกันเพื่อดำเนินงานเพื่อให้มั่นใจว่างานทั้งหมดจะถูกดำเนินการในลำดับที่ระบุ (FIFO, LIFO, ลำดับความสำคัญ)
(1) Newcachedthreadpool:
สร้างพูลเธรดที่แคช หากความยาวพูลเธรดเกินความต้องการการประมวลผลคุณสามารถรีไซเคิลเธรดที่ไม่ได้ใช้งานได้อย่างยืดหยุ่น หากไม่มีการรีไซเคิลให้สร้างเธรดใหม่ รหัสตัวอย่างมีดังนี้:
ExecutorService CachedThreadPool = Executors.newcachedThreadPool (); สำหรับ (int i = 0; i <10; i ++) {ดัชนี int สุดท้าย = i; ลอง {thread.sleep (ดัชนี * 1000); } catch (interruptedException e) {e.printStackTrace (); } cachedthreadpool.execute (ใหม่ runnable () {@overridepublic void run () {system.out.println (ดัชนี);}});}พูลเธรดไม่มีที่สิ้นสุด เมื่องานที่สองถูกดำเนินการงานแรกเสร็จสมบูรณ์และเธรดที่ดำเนินการงานแรกจะถูกนำมาใช้ซ้ำโดยไม่ต้องสร้างเธรดใหม่ทุกครั้ง
(2) newfixedthreadpool:
สร้างพูลเธรดความยาวคงที่ที่สามารถควบคุมจำนวนสูงสุดของเธรดพร้อมกันและเธรดส่วนเกินจะรอในคิว รหัสตัวอย่างมีดังนี้:
ExecutORSERVICE executedThreadPool = Executors.newFixedThreadPool (3); สำหรับ (int i = 0; i <10; i ++) {ดัชนี int สุดท้าย = i; recidethreadpool.execute (ใหม่ runnable () {@overridepublic void run () {ลอง {system.out.println (ดัชนี); thread.sleep (2000);} catch (interruptedException e) {//เนื่องจากขนาดของพูลเธรดคือ 3 ให้นอน 2 วินาทีหลังจากแต่ละดัชนีเอาต์พุตงานดังนั้นตัวเลข 3 ตัวจึงถูกพิมพ์ทุกสองวินาที
ขนาดของพูลเธรดที่มีความยาวคงที่ได้รับการตั้งค่าที่ดีที่สุดตามทรัพยากรของระบบ เช่น runtime.getruntime (). arableprocessors () โปรดดู preloaddatacache
(3) NewscheduledThreadPool:
สร้างพูลเธรดที่มีความยาวคงที่ซึ่งรองรับการดำเนินงานที่กำหนดเวลาและเป็นระยะ รหัสตัวอย่างสำหรับการดำเนินการล่าช้ามีดังนี้:
ScheduleDexecutorService ScheduleDTHREADPOOL = Executors.NewsCheduledThreadPool (5); scheduledThreadpool.schedule (ใหม่ runnable () {@overridepublic void run () {system.out.println ("ล่าช้า 3 วินาที");}}, 3, timeunit.seconds);บ่งชี้ว่าการดำเนินการล่าช้า 3 วินาที
รหัสตัวอย่างจะดำเนินการอย่างสม่ำเสมอดังนี้:
ScheduledThreadpool.scheduleatfixedrate (ใหม่ runnable () {@overridepublic void run () {system.out.println ("ล่าช้า 1 วินาทีและกระตุ้นทุก 3 วินาที");}}, 1, 3, timeunit.seconds);หมายความว่าการล่าช้าจะดำเนินการทุก 3 วินาทีหลังจาก 1 วินาที
ScheduleDexecutorService ปลอดภัยและทรงพลังกว่าตัวจับเวลา
(4) NewsingLetHreadExecutor:
สร้างพูลเธรดเดี่ยวซึ่งจะใช้เธรดคนงานที่ไม่ซ้ำกันเพื่อดำเนินการงานเพื่อให้มั่นใจว่างานทั้งหมดจะดำเนินการตามลำดับที่ระบุ (FIFO, LIFO, ลำดับความสำคัญ) รหัสตัวอย่างมีดังนี้:
ExecutorService SingLetHreadExecutor = Executors.newsingLetHreadexecutor (); สำหรับ (int i = 0; i <10; i ++) {ดัชนี int สุดท้าย = i; singlethreatHreadexecutor.execute (reunnable (@OverridePublic Void) (InterruptedException E) {// todo บล็อก catch ที่สร้างขึ้นอัตโนมัติ e.printstacktrace ();}}});}ผลลัพธ์จะถูกส่งออกตามลำดับซึ่งเทียบเท่ากับการดำเนินการแต่ละงานตามลำดับ
โปรแกรม GUI ปัจจุบันส่วนใหญ่เป็นเธรดเดี่ยว เธรดเดี่ยวใน Android สามารถใช้สำหรับการดำเนินการฐานข้อมูลการดำเนินการไฟล์การติดตั้งแบทช์ของแอปพลิเคชันการลบแบทช์แอปพลิเคชัน ฯลฯ ซึ่งไม่เหมาะสำหรับการเกิดขึ้นพร้อมกัน แต่อาจบล็อก IO และส่งผลต่อการตอบสนองของเธรด UI
ฟังก์ชั่นของพูลเธรด:
ฟังก์ชั่นของพูลเธรดคือการ จำกัด จำนวนเธรดที่ดำเนินการในระบบ
ขึ้นอยู่กับสภาพแวดล้อมของระบบจำนวนเธรดสามารถตั้งค่าโดยอัตโนมัติหรือด้วยตนเองเพื่อให้ได้เอฟเฟกต์การทำงานที่ดีที่สุด ทรัพยากรระบบน้อยลงจะสูญเปล่าและความแออัดของระบบไม่สูง ใช้พูลเธรดเพื่อควบคุมจำนวนเธรดและเธรดอื่น ๆ กำลังรออยู่ในบรรทัด หลังจากดำเนินการงานแล้วงานแรกจะถูกนำมาจากคิวเพื่อเริ่มดำเนินการ หากไม่มีกระบวนการรออยู่ในคิวทรัพยากรของพูลเธรดกำลังรออยู่ เมื่อต้องทำงานงานใหม่หากมีเธรดคนงานที่รออยู่ในพูลเธรดก็สามารถเริ่มทำงานได้ มิฉะนั้นจะเข้าสู่คิวรอ
ทำไมต้องใช้พูลเธรด:
1. ลดจำนวนเธรดครั้งที่ถูกสร้างและทำลายและเธรดคนงานแต่ละคนสามารถนำกลับมาใช้ใหม่และสามารถทำงานได้หลายงาน
2. จำนวนเธรดคนงานในพูลเธรดสามารถปรับได้ตามความสามารถของระบบในการป้องกันไม่ให้เซิร์ฟเวอร์ถูกดูดลงเนื่องจากการใช้หน่วยความจำมากเกินไป (แต่ละเธรดต้องใช้หน่วยความจำประมาณ 1MB
อินเทอร์เฟซระดับบนสุดของพูลเธรดใน Java เป็นผู้ดำเนินการ แต่พูดอย่างเคร่งครัด Executor ไม่ใช่พูลเธรด แต่เป็นเพียงเครื่องมือสำหรับการดำเนินการเธรด อินเทอร์เฟซพูลเธรดจริงคือ ExecutorService
หมวดหมู่ที่สำคัญอีกหลายประเภท:
ExecutorService: อินเทอร์เฟซพูลเธรดจริง
ScheduleDexecutorService: มันสามารถคล้ายกับตัวจับเวลา/timertask การแก้ปัญหาที่ต้องใช้งานซ้ำ
ThreadPoolexecutor: การใช้งานเริ่มต้นของ ExecutorService
ScheduledThreadPoolexecutor: การใช้งานคลาสของอินเตอร์เฟส SchedUleDExecutorService ที่สืบทอด ThreadPoolexecutor ซึ่งเป็นระยะเวลาการใช้งานการจัดตารางงานเป็นระยะ
มันค่อนข้างซับซ้อนในการกำหนดค่าพูลเธรดโดยเฉพาะอย่างยิ่งเมื่อหลักการของพูลเธรดไม่ชัดเจนมาก มีโอกาสมากที่พูลเธรดที่กำหนดค่าจะไม่ดีกว่า ดังนั้นโรงงานคงที่บางแห่งมีให้ในคลาสผู้บริหารเพื่อสร้างพูลเธรดที่ใช้กันทั่วไป
1. newsinglethreadexecutor
สร้างพูลเธรดเดียว พูลเธรดนี้มีเพียงเธรดเดียวที่ใช้งานได้ซึ่งเทียบเท่ากับเธรดเดียวที่ทำงานทั้งหมดในอนุกรม หากเธรดที่ไม่ซ้ำกันนี้สิ้นสุดลงเนื่องจากข้อยกเว้นจะมีเธรดใหม่ที่จะแทนที่ พูลเธรดนี้ทำให้มั่นใจได้ว่าคำสั่งการดำเนินการของงานทั้งหมดจะดำเนินการตามลำดับของการส่งงาน
2. NewFixedThreadPool
สร้างพูลเธรดขนาดคงที่ ทุกครั้งที่มีการส่งงานเธรดจะถูกสร้างขึ้นจนกว่าเธรดจะมีขนาดสูงสุดของพูลเธรด ขนาดพูลเธรดยังคงเหมือนเดิมเมื่อถึงค่าสูงสุด หากเธรดสิ้นสุดลงเนื่องจากข้อยกเว้นการดำเนินการพูลเธรดจะเพิ่มเธรดใหม่
3. Newcachedthreadpool
สร้างพูลเธรดที่แคช หากขนาดพูลเธรดเกินเธรดที่จำเป็นในการประมวลผลงาน
จากนั้นบางเธรดที่ไม่ได้ใช้งาน (ไม่มีการดำเนินการใน 60 วินาที) จะถูกนำกลับมาใช้ใหม่ เมื่อจำนวนงานเพิ่มขึ้นพูลเธรดนี้สามารถเพิ่มเธรดใหม่ได้อย่างชาญฉลาดเพื่อจัดการงาน พูลเธรดนี้ไม่ได้ จำกัด ขนาดพูลเธรดซึ่งขึ้นอยู่กับขนาดเธรดสูงสุดที่ระบบปฏิบัติการ (หรือ JVM) สามารถสร้างได้
4. NewscheduledThreadpool
สร้างพูลเธรดที่มีขนาดไม่ จำกัด พูลเธรดนี้รองรับความจำเป็นในการทำงานเป็นระยะและเป็นระยะ
รหัสตัวอย่าง
1. พูลเธรดขนาดคงที่, newfixedthreadpool:
Package App.executors; นำเข้า java.util.concurrent.executors; นำเข้า java.util.concurrent.executorservice; / ** * java เธรด: เธรดพูล * * @author xiho */ การทดสอบคลาสสาธารณะ {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {// สร้างพูลเธรดที่มีจำนวนคงที่ของเธรดที่ใช้ซ้ำได้ // สร้างเธรดเธรด t1 = new MyThread (); เธรด t2 = ใหม่ mythread (); เธรด t3 = ใหม่ mythread (); เธรด t4 = ใหม่ mythread (); เธรด t5 = ใหม่ mythread (); // ใส่เธรดลงในพูลสำหรับการดำเนินการพูล Execute (T1); pool.execute (T2); pool.execute (T3); pool.execute (T4); pool.execute (T5); // ปิดพูลพูลเธรด shutdown (); }} คลาส mythread ขยายเธรด {@override โมฆะสาธารณะเรียกใช้ () {system.out.println (thread.currentthread (). getName () + "การดำเนินการ ... "); -ผลลัพธ์ผลลัพธ์:
Pool-1-Thread-1 กำลังดำเนินการ - - Pool-1-Thread-3 กำลังดำเนินการ - - Pool-1-Thread-4 กำลังดำเนินการ - - Pool-1-Thread-2 กำลังดำเนินการ - - Pool-1-Thread-5 กำลังดำเนินการ - -
เปลี่ยนพารามิเตอร์ใน ExecutoRservice Pool = Executors.NewFixedThreadPool (5): ExecutoRservice Pool = Executors.newFixedThreadPool (2) และผลลัพธ์ผลลัพธ์คือ:
Pool-1-Thread-1 กำลังดำเนินการ - - Pool-1-Thread-1 กำลังดำเนินการ - - Pool-1-Thread-2 กำลังดำเนินการ - - Pool-1-Thread-1 กำลังดำเนินการ - - Pool-1-Thread-2 กำลังดำเนินการ - -
จากผลลัพธ์ข้างต้นเราจะเห็นว่าพารามิเตอร์ของ NewFixedThreadPool ระบุจำนวนเธรดสูงสุดที่สามารถเรียกใช้ได้ หลังจากเพิ่มมากกว่าจำนวนเธรดนี้พวกเขาจะไม่ทำงาน ประการที่สองเธรดที่เพิ่มลงในพูลเธรดอยู่ในสถานะที่มีการจัดการและการดำเนินการของเธรดจะไม่ได้รับผลกระทบจากคำสั่งการเข้าร่วม
2. พูลเธรดงานเดี่ยว, newsingLetHreadExecutor:
เพียงเปลี่ยน ExecutoRservice Pool = Executors.newFixedThreadPool (2) ในรหัสด้านบนเป็น ExecutorService Pool = Executors.newsingLetHreathedExecutor ();
ผลลัพธ์ผลลัพธ์:
Pool-1-Thread-1 กำลังดำเนินการ - - Pool-1-Thread-1 กำลังดำเนินการ - - Pool-1-Thread-1 กำลังดำเนินการ - - Pool-1-Thread-1 กำลังดำเนินการ - - Pool-1-Thread-1 กำลังดำเนินการ - -
จะเห็นได้ว่าทุกครั้งที่คุณเรียกวิธีการดำเนินการวิธีการเรียกใช้เธรด -1 จะถูกเรียกในตอนท้าย
3. พูลเกลียวขนาดตัวแปร, newcachedthreadpool:
คล้ายกับข้างต้นเพียงแค่เปลี่ยนวิธีการสร้างพูล: ExecutorService Pool = Executors.newcachedThreadPool ();
ผลลัพธ์ผลลัพธ์:
Pool-1-Thread-1 กำลังดำเนินการ - - Pool-1-Thread-2 กำลังดำเนินการ - - Pool-1-Thread-4 กำลังดำเนินการ - - Pool-1-Thread-3 กำลังดำเนินการ - - Pool-1-Thread-5 กำลังดำเนินการ - -
วิธีนี้มีลักษณะโดยความจริงที่ว่าสามารถสร้างพูลเธรดใหม่ได้ตามต้องการ แต่จะถูกนำกลับมาใช้ใหม่เมื่อมีเธรดที่สร้างขึ้นก่อนหน้านี้
4. พูลการเชื่อมต่อล่าช้า NewscheduledThreadPool:
Public Class TestscheduledThreadPoolexecutor {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {ScheduleDTHreadPoolexecutor exec = ใหม่ scheduledThreadPoolexecutor (1); exec.scheduleatfixedrate (ใหม่ runnable () {// ข้อยกเว้นจะถูกกระตุ้นทุกครั้งในขณะที่ @Override PublicVoid Run () {// โยน runtimeException ใหม่ (); System.out.println ("========================================================================================= - - - TimeUnit.milliseconds); Exec.ScheduleatFixedrate (ใหม่ runnable () {// พิมพ์เวลาของระบบทุกครั้งในขณะที่พิสูจน์ว่าทั้งสองไม่มีอิทธิพลต่อกันและกัน @Override PublicVoid Run ()ผลลัพธ์ผลลัพธ์:
================= 838464454951683866438290348388643830710 ================ 83906438513838383839264646464
ข้างต้นเป็นเรื่องเกี่ยวกับบทความนี้ฉันหวังว่ามันจะเป็นประโยชน์กับการเรียนรู้ของทุกคน