เธรดกับ ThreadPool


137

ความแตกต่างระหว่างการใช้เธรดใหม่และการใช้เธรดจากเธรดพูลคืออะไร? มีประโยชน์ด้านประสิทธิภาพอะไรบ้างและเหตุใดฉันจึงควรพิจารณาใช้เธรดจากพูลแทนที่จะใช้เธรดที่ฉันสร้างขึ้นอย่างชัดเจน ฉันกำลังคิดถึง. NET ที่นี่โดยเฉพาะ แต่ตัวอย่างทั่วไปก็ใช้ได้

คำตอบ:


111

เธรดพูลจะให้ประโยชน์สำหรับการดำเนินการบ่อยและค่อนข้างสั้นโดย

  • การนำเธรดที่สร้างไว้แล้วกลับมาใช้ใหม่แทนที่จะสร้างใหม่ (กระบวนการที่มีราคาแพง)
  • การควบคุมอัตราการสร้างเธรดเมื่อมีคำขอรายการงานใหม่จำนวนมาก (ฉันเชื่อว่านี่เป็นเพียงใน. NET 3.5)

    • หากคุณจัดคิวงานพูลเธรด 100 เธรดจะใช้เฉพาะเธรดจำนวนมากเท่าที่สร้างไว้แล้วเพื่อรองรับการร้องขอเหล่านี้ (เช่น 10 เช่น) เธรดพูลจะทำการตรวจสอบบ่อยครั้ง (ฉันเชื่อว่าทุกๆ 500ms ใน 3.5 SP1) และหากมีงานที่อยู่ในคิวก็จะสร้างเธรดใหม่หนึ่งชุด หากงานของคุณรวดเร็วจำนวนเธรดใหม่จะน้อยและการนำเธรด 10 หรือมากกว่านั้นกลับมาใช้ใหม่สำหรับงานสั้น ๆ จะเร็วกว่าการสร้างเธรด 100 เธรดขึ้นข้างหน้า

    • หากปริมาณงานของคุณมีคำขอพูลเธรดจำนวนมากเข้ามาอย่างต่อเนื่องเธรดพูลจะปรับตัวเองให้เข้ากับปริมาณงานของคุณโดยการสร้างเธรดเพิ่มเติมในพูลตามกระบวนการข้างต้นเพื่อให้มีเธรดจำนวนมากขึ้นเพื่อประมวลผลคำขอ

    • ตรวจสอบที่นี่สำหรับข้อมูลเชิงลึกเพิ่มเติมเกี่ยวกับการทำงานของเธรดพูลภายใต้ประทุน

การสร้างเธรดใหม่ด้วยตัวคุณเองจะเหมาะสมกว่าหากงานกำลังจะดำเนินไปค่อนข้างนาน (อาจใช้เวลาประมาณหนึ่งหรือสองวินาที แต่ขึ้นอยู่กับสถานการณ์เฉพาะ)

@Krzysztof - เธรดพูลเธรดคือเธรดพื้นหลังที่จะหยุดเมื่อเธรดหลักสิ้นสุดลง เธรดที่สร้างขึ้นด้วยตนเองจะอยู่เบื้องหน้าตามค่าเริ่มต้น (จะทำงานต่อไปหลังจากเธรดหลักสิ้นสุดลง) แต่สามารถตั้งค่าเป็นพื้นหลังก่อนที่จะเรียกเริ่มบนเธรดเหล่านั้น


5
สิ่งเดียวที่ฉันสงสัยคือคำสั่งต่อไปนี้จาก MSDN ( msdn.microsoft.com/en-us/library/1c9txz50.aspx ) "เธรดพื้นหลังจะรันก็ต่อเมื่อจำนวนเธรดเบื้องหน้าที่ดำเนินการน้อยกว่าจำนวนตัวประมวลผล . ". นั่นหมายความว่าเมื่อแบ่งงานระหว่างคอร์ที่เธรดเบื้องหน้าได้รับลำดับความสำคัญ?
cdiggins

1
➤คุณไม่สามารถยกเลิกหรือขัดจังหวะเธรดจากเธรดพูลได้ ➤คุณไม่สามารถเข้าร่วมเธรดจากกลุ่มเธรดได้ เพื่อให้บรรลุเป้าหมายนี้คุณต้องใช้กลไกอื่น ๆ
Zinov

15

เธรดพูลที่มีการจัดการ. NET: -

  • ปรับขนาดตามปริมาณงานปัจจุบันและฮาร์ดแวร์ที่มี
  • ประกอบด้วยเธรดของผู้ปฏิบัติงานและเธรดพอร์ตที่สมบูรณ์ (ซึ่งใช้เพื่อให้บริการ IO โดยเฉพาะ)
  • ได้รับการปรับให้เหมาะสมสำหรับการดำเนินการที่ค่อนข้างสั้นจำนวนมาก

มีการใช้เธรดพูลอื่น ๆ ที่อาจเหมาะสมกว่าสำหรับการดำเนินการที่รันเป็นเวลานาน

โดยเฉพาะใช้เธรดพูลเพื่อป้องกันไม่ให้แอปของคุณสร้างเธรดมากเกินไป คุณลักษณะที่สำคัญที่สุดของเธรดพูลคือคิวงาน นั่นคือเมื่อเครื่องของคุณมีงานยุ่งเพียงพอเธรดพูลจะจัดคิวคำขอแทนที่จะสร้างเธรดเพิ่มเติมทันที

ดังนั้นหากคุณจะสร้างเธรดขนาดเล็กจำนวน จำกัด ให้สร้างเธรดด้วยตัวคุณเอง หากคุณไม่สามารถระบุล่วงหน้าได้ว่าจะสร้างเธรดจำนวนเท่าใด (เช่นสร้างขึ้นเพื่อตอบสนองต่อ IO ที่เข้ามา) และงานของพวกเขาจะมีอายุสั้นให้ใช้เธรดพูล หากคุณไม่ทราบว่ามีจำนวนเท่าใด แต่งานของพวกเขาจะใช้งานได้ยาวนานไม่มีอะไรในแพลตฟอร์มที่จะช่วยคุณได้ แต่คุณอาจสามารถค้นหาการใช้งานเธรดพูลอื่นที่เหมาะสมได้


ใน. NET คุณสามารถใช้พอร์ตที่สมบูรณ์โดยไม่มีเธรดพูลได้หรือไม่ ฉันอยู่ภายใต้สมมติฐานที่ว่าวิธี async I / O เป็นวิธีเดียว (ใน. NET) และพวกเขาใช้เธรดพูล
Karg

11

ด้วย

new Thread().Start()

วางไข่เธรด Foreground ที่จะไม่ตายหากคุณปิดโปรแกรมของคุณ เธรด ThreadPool คือเธรดพื้นหลังที่ตายเมื่อคุณปิดแอพ


11
คุณสามารถตั้งค่าเธรดเป็นพื้นหลังได้ตลอดเวลา เป็นเพียงฉากหน้าโดยปริยาย
Kris Erickson

3
nemo: var t = เธรดใหม่ (... ); t.BackgroundThread = จริง; t.Start ();
Ricardo Amores

18
คำชี้แจงเกี่ยวกับคำว่า "โปรแกรม" แอปพลิเคชันเดสก์ท็อปทำงานในกระบวนการและมีเธรดเบื้องหน้าอย่างน้อยหนึ่งเธรดที่จัดการ UI กระบวนการนั้นจะทำงานต่อไปตราบเท่าที่มีเธรดเบื้องหน้า เมื่อคุณปิดแอปพลิเคชันเดสก์ท็อปเธรด UI เบื้องหน้าจะหยุด แต่คุณไม่จำเป็นต้องหยุดกระบวนการหากมีเธรดเบื้องหน้าอื่น ๆ
G-Wiz

8

ฉันอยากรู้อยากเห็นเกี่ยวกับการใช้ทรัพยากรสัมพัทธ์สำหรับสิ่งเหล่านี้และและใช้เกณฑ์มาตรฐานในแล็ปท็อป Intel i5 แบบดูอัลคอร์ปี 2012 ของฉันโดยใช้. net 4.0 release build บน windows 8 Thread Pools ใช้เวลาโดยเฉลี่ย 0.035ms ในการเริ่มต้นโดยที่ Threads ใช้เวลาเฉลี่ย 5.06 นางสาว. กล่าวอีกนัยหนึ่งเธรดในพูลเริ่มเร็วขึ้นประมาณ 300 เท่าสำหรับเธรดอายุสั้นจำนวนมาก อย่างน้อยในช่วงทดสอบ (100-2000) เธรดเวลาทั้งหมดต่อเธรดดูเหมือนจะคงที่

นี่คือรหัสที่ถูกเปรียบเทียบ:

    for (int i = 0; i < ThreadCount; i++) {
        Task.Run(() => { });
    }

    for (int i = 0; i < ThreadCount; i++) {
        var t = new Thread(() => { });
        t.Start();
    }

ป้อนคำอธิบายภาพที่นี่


5
ฉันคิดว่าเป็นเพราะ ThreadPool นำเธรดที่สร้างขึ้นมาใช้ซ้ำแทนที่จะสร้างใหม่ (แพงมาก)
fabriciorissetto

3

ตรวจสอบที่นี่สำหรับเธรดก่อนหน้านี้:

เมื่อใดที่ฉันไม่ควรใช้ ThreadPool ใน. Net

สรุปก็คือ Threadpool เป็นสิ่งที่ดีหากคุณต้องการสร้างเธรดแบบสั้นจำนวนมากในขณะที่การใช้เธรดจะช่วยให้คุณควบคุมได้มากขึ้นเล็กน้อย


1

พื้นที่จัดเก็บเธรดในเครื่องไม่ใช่ความคิดที่ดีสำหรับเธรดพูล มันทำให้เธรดเป็น "เอกลักษณ์"; เธรดทั้งหมดไม่เท่ากันอีกต่อไป ตอนนี้เธรดพูลมีประโยชน์อย่างยิ่งหากคุณต้องการเธรดที่เหมือนกันจำนวนมากพร้อมที่จะทำงานของคุณโดยไม่ต้องสร้างค่าใช้จ่าย


1

หากคุณต้องการเธรดจำนวนมากคุณอาจต้องการใช้ ThreadPool พวกเขาใช้เธรดซ้ำช่วยให้คุณประหยัดค่าใช้จ่ายในการสร้างเธรด

หากคุณต้องการเพียงเธรดเดียวเพื่อทำบางสิ่งบางอย่างเธรดน่าจะง่ายที่สุด


1

ความต้องการหลักสำหรับเธรด Adpool คือการจัดการงานสั้น ๆ ที่คาดว่าจะเสร็จสมบูรณ์เกือบจะในทันที ตัวจัดการการขัดจังหวะฮาร์ดแวร์มักจะทำงานในบริบทที่ซ้อนกันซึ่งจะไม่เหมาะสำหรับโค้ดที่ไม่ใช่เคอร์เนล แต่ตัวจัดการการขัดจังหวะฮาร์ดแวร์อาจค้นพบว่าควรเรียกใช้การเรียกกลับการเสร็จสิ้น I / O ในโหมดผู้ใช้โดยเร็วที่สุด การสร้างเธรดใหม่เพื่อจุดประสงค์ในการเรียกใช้สิ่งดังกล่าวจะเป็นการใช้งานมากเกินไป การมีเธรดที่สร้างไว้ล่วงหน้าเพียงไม่กี่เธรดซึ่งสามารถส่งไปเพื่อเรียกใช้การเรียกกลับการเสร็จสิ้น I / O หรือสิ่งอื่นที่คล้ายคลึงกันนั้นมีประสิทธิภาพมากกว่ามาก

ลักษณะสำคัญของเธรดดังกล่าวคือถ้าเมธอดการเติม I / O เสร็จสมบูรณ์โดยทันทีเป็นหลักและไม่บล็อกและจำนวนเธรดดังกล่าวที่รันเมธอดในปัจจุบันอย่างน้อยเท่ากับจำนวนโปรเซสเซอร์วิธีเดียวที่เธรดอื่น ๆ สามารถรันได้ก่อนที่วิธีการใดวิธีการหนึ่งที่กล่าวถึงข้างต้นจะเสร็จสิ้นหากวิธีการอื่นใดบล็อกหรือเวลาดำเนินการเกินกว่าช่วงเวลาเธรดปกติ สิ่งเหล่านี้ไม่ควรเกิดขึ้นบ่อยนักหากมีการใช้เธรดพูลตามที่ตั้งใจไว้

หากไม่สามารถคาดหมายว่าเมธอดจะออกภายใน 100ms เมื่อเริ่มดำเนินการเมธอดควรดำเนินการด้วยวิธีการอื่นที่ไม่ใช่เธรดพูลหลัก หากมีงานจำนวนมากที่ต้องดำเนินการซึ่งมี CPU เข้มข้น แต่จะไม่ปิดกั้นอาจเป็นประโยชน์ในการจัดส่งโดยใช้ชุดเธรดของแอปพลิเคชัน (หนึ่งชุดต่อแกน CPU) ซึ่งแยกจากเธรดพูล "หลัก" เนื่องจากใช้ เธรดที่มากกว่าคอร์จะถูกต่อต้านเมื่อรันงานที่ต้องใช้ CPU มากโดยไม่ปิดกั้น อย่างไรก็ตามหากวิธีการใช้เวลาหนึ่งวินาทีหรือนานกว่านั้นในการดำเนินการและจะใช้เวลาส่วนใหญ่ในการบล็อกเมธอดนั้นควรจะรันในเธรดเฉพาะและแทบจะไม่ถูกรันในเธรดพูลเธรดหลัก หากการดำเนินการที่รันเป็นเวลานานจำเป็นต้องถูกทริกเกอร์โดยบางสิ่งเช่นการเรียกกลับ I / O


0

โดยทั่วไป (ฉันไม่เคยใช้. NET) เธรดพูลจะถูกใช้เพื่อวัตถุประสงค์ในการจัดการทรัพยากร ช่วยให้สามารถกำหนดค่าข้อ จำกัด ลงในซอฟต์แวร์ของคุณได้ นอกจากนี้ยังอาจทำได้ด้วยเหตุผลด้านประสิทธิภาพเนื่องจากการสร้างเธรดใหม่อาจมีค่าใช้จ่ายสูง

นอกจากนี้ยังอาจมีเหตุผลเฉพาะของระบบ ใน Java (อีกครั้งฉันไม่รู้ว่าสิ่งนี้ใช้กับ. NET หรือไม่) ผู้จัดการของเธรดอาจใช้ตัวแปรเฉพาะของเธรดเนื่องจากแต่ละเธรดถูกดึงออกจากพูลและยกเลิกการตั้งค่าเมื่อส่งคืน (วิธีทั่วไปในการส่งผ่านสิ่งต่างๆเช่น ตัวตน).

ข้อ จำกัด ตัวอย่าง: ฉันมีการเชื่อมต่อ 10 db เท่านั้นดังนั้นฉันจึงอนุญาตเธรดผู้ปฏิบัติงาน 10 เธรดเท่านั้นในการเข้าถึงฐานข้อมูล

นี่ไม่ได้หมายความว่าคุณไม่ควรสร้างเธรดของคุณเอง แต่มีเงื่อนไขที่เหมาะสมที่จะใช้พูล


0

การใช้พูลเป็นความคิดที่ดีหากคุณไม่รู้หรือไม่สามารถควบคุมได้ว่าจะสร้างเธรดจำนวนเท่าใด

เพียงแค่มีปัญหากับแบบฟอร์มที่ใช้เธรดเพื่ออัปเดตฟิลด์บางส่วนจากฐานข้อมูลในเหตุการณ์ที่มีการเปลี่ยนแปลงตำแหน่งของการควบคุมรายการ (หลีกเลี่ยง freez) ผู้ใช้ของฉันใช้เวลา 5 นาทีในการเกิดข้อผิดพลาดจากฐานข้อมูล (เชื่อมต่อกับ Access มากเกินไป) เพราะเขาเปลี่ยนตำแหน่งรายการเร็วเกินไป ...

ฉันรู้ว่ามีวิธีอื่นในการแก้ไขปัญหาพื้นฐาน (รวมถึงการไม่ใช้การเข้าถึง) แต่การรวมกลุ่มเป็นการเริ่มต้นที่ดี


0

ด้าย :

  1. การสร้างเธรดนั้นช้ากว่าการใช้เธรดพูลมาก
  2. คุณสามารถเปลี่ยนลำดับความสำคัญของเธรดได้
  3. จำนวนเธรดสูงสุดในกระบวนการที่เกี่ยวข้องกับทรัพยากร
  4. เธรดอยู่ที่ระดับ OS และควบคุมโดย OS
  5. การใช้เธรดเป็นตัวเลือกที่ดีกว่าเมื่องานใช้งานค่อนข้างนาน

เธรด - พูล :

  1. การรันเธรดบนเธรดพูลนั้นเร็วกว่าการสร้างเธรดโดยตรงมาก
  2. คุณไม่สามารถเปลี่ยนลำดับความสำคัญของการรันเธรดตามเธรดพูล
  3. มีเธรดพูลเดียวต่อกระบวนการ
  4. เธรดพูลถูกจัดการโดย CLR
  5. เธรดพูลมีประโยชน์สำหรับการทำงานที่มีอายุสั้น
  6. จำนวนเธรดในเธรดพูลเกี่ยวข้องกับการโหลดแอ็พพลิเคชัน
  7. งาน TPL รันโดยใช้เธรดพูล
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.