การสร้างเธรด Java มีราคาแพงเนื่องจากมีงานที่เกี่ยวข้อง:
- หน่วยความจำขนาดใหญ่ต้องถูกจัดสรรและกำหนดค่าเริ่มต้นสำหรับสแตกเธรด
- จำเป็นต้องทำการเรียกระบบเพื่อสร้าง / ลงทะเบียนเธรดดั้งเดิมกับโฮสต์ระบบปฏิบัติการ
- ตัวอธิบายจำเป็นต้องสร้างเริ่มต้นและเพิ่มลงในโครงสร้างข้อมูล JVM- ภายใน
นอกจากนี้ยังมีราคาแพงในแง่ที่ว่าเธรดผูกทรัพยากรตราบเท่าที่ยังมีชีวิตอยู่; เช่นเธรดสแต็กวัตถุใด ๆ ที่สามารถเข้าถึงได้จากสแต็กตัวอธิบายเธรด JVM ตัวบ่งชี้เธรด OS ดั้งเดิม
ค่าใช้จ่ายของทุกสิ่งเหล่านี้เป็นแพลตฟอร์มเฉพาะ แต่ไม่ถูกในแพลตฟอร์ม Java ใด ๆ ที่ฉันเคยเจอ
การค้นหาของ Google พบว่าฉันเป็นเกณฑ์มาตรฐานเก่าที่รายงานอัตราการสร้างเธรดที่ ~ 4000 ต่อวินาทีใน Sun Java 1.4.1 บนโปรเซสเซอร์วินเทจดูอัล Xeon ปี 2002 ใช้ Xeon วินเทจ 2002 แพลตฟอร์มที่ทันสมัยกว่านี้จะให้ตัวเลขที่ดีกว่า ... และฉันไม่สามารถให้ความเห็นเกี่ยวกับวิธีการ ... แต่อย่างน้อยมันก็ให้ ballpark สำหรับการสร้างเธรดราคาแพงที่น่าจะเป็น
การเปรียบเทียบของปีเตอร์ลอว์เรย์ระบุว่าการสร้างเธรดนั้นเร็วขึ้นอย่างมากในวันนี้ในแง่ที่แน่นอน แต่ก็ไม่มีความชัดเจนว่านี่เป็นการปรับปรุงใน Java และ / หรือ OS ... หรือความเร็วโปรเซสเซอร์ที่สูงขึ้น แต่ตัวเลขของเขายังคงบ่งบอกถึงการปรับปรุงแบบพับมากกว่า 150+ ถ้าคุณใช้กลุ่มเธรดกับการสร้าง / เริ่มเธรดใหม่ทุกครั้ง (และเขาชี้ให้เห็นว่านี่คือญาติทั้งหมด ... )
(ข้างต้นถือว่าเป็น "เธรดดั้งเดิม" แทนที่จะเป็น "เธรดสีเขียว" แต่ JVM สมัยใหม่ทั้งหมดใช้เธรดดั้งเดิมเพื่อเหตุผลด้านประสิทธิภาพเธรดสีเขียวอาจถูกกว่าในการสร้าง แต่คุณชำระในพื้นที่อื่น ๆ )
ฉันได้ทำการขุดเล็กน้อยเพื่อดูว่าสแต็กของเธรด Java ได้รับการจัดสรรอย่างไร ในกรณีของ OpenJDK 6 บน Linux เธรดสแต็กจะถูกจัดสรรโดยการเรียกไปpthread_create
ที่สร้างเธรดดั้งเดิม (JVM ไม่ผ่านpthread_create
การจัดสรรล่วงหน้า)
จากนั้นภายในpthread_create
สแต็กจะถูกจัดสรรโดยการเรียกmmap
ดังนี้:
mmap(0, attr.__stacksize,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
ตามman mmap
การMAP_ANONYMOUS
ตั้งค่าสถานะทำให้หน่วยความจำถูกเตรียมใช้งานเป็นศูนย์
ดังนั้นแม้ว่าอาจไม่จำเป็นที่สแต็กเธรด Java ใหม่จะเป็นศูนย์ (ตามข้อกำหนด JVM) ในทางปฏิบัติ (อย่างน้อยกับ OpenJDK 6 บน Linux) พวกเขาจะถูกทำให้เป็นศูนย์