เหตุใดการวางไข่ในคอนเทนเนอร์ Java EE จึงไม่สนับสนุน


120

สิ่งแรกที่ฉันได้เรียนรู้เกี่ยวกับการพัฒนา Java EE คือฉันไม่ควรวางเธรดของตัวเองภายในคอนเทนเนอร์ Java EE แต่พอมาคิดดูแล้วไม่รู้เหตุผล

คุณสามารถอธิบายได้อย่างชัดเจนว่าทำไมถึงท้อแท้?

ฉันแน่ใจว่าแอปพลิเคชันระดับองค์กรส่วนใหญ่ต้องการงานแบบอะซิงโครนัสเช่น mail daemons เซสชันที่ไม่ได้ใช้งานงานล้างข้อมูลเป็นต้น

ดังนั้นหากไม่ควรเกิดเธรดจริง ๆ วิธีที่ถูกต้องในการทำเมื่อจำเป็นคืออะไร?


4
งานอะซิงโครนัสมักจะทำโดยใช้การส่งข้อความ JMS และ MDB
Ken Liu

5
ปัญหานี้ควรจะกลายเป็นอดีตไปแล้วเมื่อใช้JSR 236ในคอนเทนเนอร์
letmaik

5
มันถูกท้อแท้เพราะหัวข้อที่สองที่ควรจะสร้างและจัดการโดยภาชนะเพื่อให้ด้ายจะมีการเข้าถึงทรัพยากรขององค์กรอื่น ๆ ด้วย Java EE7 มีมาตรฐานและวิธีที่ถูกต้องในการสร้างเธรดในสภาพแวดล้อมขององค์กร ด้วยการใช้ Concurrency Utils คุณต้องแน่ใจว่าเธรดใหม่ของคุณถูกสร้างขึ้นและจัดการโดยคอนเทนเนอร์ซึ่งรับประกันว่ามีบริการ EE ทั้งหมด ตัวอย่างที่นี่
Chris Ritchie

สามารถดูวิธีที่ถูกต้องหลายประการในมุมมอง JSF / EJB ได้ที่นี่: stackoverflow.com/q/6149919
BalusC

คำตอบ:


84

เป็นสิ่งที่ไม่สนับสนุนเนื่องจากทรัพยากรทั้งหมดภายในสภาพแวดล้อมมีไว้เพื่อจัดการและอาจถูกตรวจสอบโดยเซิร์ฟเวอร์ นอกจากนี้บริบทส่วนใหญ่ที่ใช้เธรดมักจะแนบกับเธรดของการดำเนินการเอง หากคุณเพิ่งเริ่มเธรดของคุณเอง (ซึ่งฉันเชื่อว่าเซิร์ฟเวอร์บางตัวไม่อนุญาตด้วยซ้ำ) จะไม่สามารถเข้าถึงทรัพยากรอื่น ๆ ได้ สิ่งนี้หมายความว่าคุณไม่สามารถรับ InitialContext และทำการค้นหา JNDI เพื่อเข้าถึงทรัพยากรระบบอื่น ๆ เช่น JMS Connection Factories และ Datasources

มีหลายวิธีในการดำเนินการนี้ "อย่างถูกต้อง" แต่ขึ้นอยู่กับแพลตฟอร์มที่ใช้

Commonj WorkManager เป็นเรื่องปกติสำหรับ WebSphere และ WebLogic รวมถึงอื่น ๆ

ข้อมูลเพิ่มเติมที่นี่

และที่นี่

นอกจากนี้ยังค่อนข้างซ้ำกันนี้จากเช้าวันนี้

อัปเดต: โปรดทราบว่าคำถามและคำตอบนี้เกี่ยวข้องกับสถานะของ Java EE ในปี 2009 สิ่งต่างๆได้ดีขึ้นตั้งแต่นั้นมา!


1
คุณไม่สามารถรับ InitialContext และทำการค้นหา JNDI เพื่อเข้าถึงทรัพยากรระบบอื่น ๆ เช่น JMS Connection Factories และ Datasources ฉันมีแอปที่ใช้งานได้โดยการฉีดแหล่งข้อมูลเมื่อเริ่มต้นเธรด แต่ฉันอาจต้องคิดใหม่ในแนวทางนี้ ...
rjohnston

6
ขณะนี้มีวิธีมาตรฐานและวิธีที่ถูกต้องในการสร้างเธรดด้วย Java EE API หลัก ด้วยการใช้ Concurrency Utils คุณต้องแน่ใจว่าเธรดใหม่ของคุณถูกสร้างขึ้นและจัดการโดยคอนเทนเนอร์ซึ่งรับประกันว่ามีบริการ EE ทั้งหมด ตัวอย่างที่นี่และที่นี่
Chris Ritchie

@ChrisRitchie ขอบคุณสำหรับคำแนะนำ ถ้าเฉพาะ JBoss AS / IBM WAS ที่รองรับ Java EE 7 ... :-(
asgs

1
@asgs WildFly 8 (ชื่อใหม่สำหรับ JBoss AS) ไม่สนับสนุน Java EE 7. ไอบีเอ็มเป็นเพียง Java EE 6 ได้รับการรับรองการรับรอง
คริสริตชี่

34

สำหรับ EJB นั้นไม่เพียง แต่ท้อใจเท่านั้น แต่ยังห้ามโดยชัดแจ้งตามข้อกำหนด :

Enterprise bean ต้องไม่ใช้พื้นฐานการซิงโครไนซ์เธรดเพื่อซิงโครไนซ์การดำเนินการของหลายอินสแตนซ์

และ

Enterprise bean ต้องไม่พยายามจัดการเธรด Enterprise bean ต้องไม่พยายามเริ่มต้นหยุดระงับหรือดำเนินการต่อเธรดหรือเปลี่ยนลำดับความสำคัญหรือชื่อของเธรด Enterprise bean ต้องไม่พยายามจัดการกลุ่มเธรด

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


3
Java EE7 Concurrency Utils จัดเตรียมวิธีที่ถูกต้องในการสร้างเธรดในสภาพแวดล้อมขององค์กร ตัวอย่างที่นี่และที่นี่
Chris Ritchie

1
@ คุณช่วยอธิบายให้ฉันฟังได้ไหมว่าทำไมเธรดจึงเป็นอุปสรรคสำคัญในการเคลื่อนย้าย EJB จากเครื่องหนึ่งไปยังอีกเครื่องหนึ่ง
Geek

13

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

นี่คือเหตุผลที่มาจากบริการจับเวลา J2EE 1.4 ดูนี้บทความสำหรับรายละเอียด


2
JSR 236 เพิ่มคุณสมบัติเพื่อรองรับเธรดการวางไข่ใน Java EE 7 และใหม่กว่า ดูคำตอบนี้พี่น้องโดยคริสริตชี่
Basil Bourque

8

ยูทิลิตี้การทำงานพร้อมกันสำหรับ Java EE

ขณะนี้มีวิธีมาตรฐานและวิธีที่ถูกต้องในการสร้างเธรดด้วย Java EE API หลัก:

ด้วยการใช้ Concurrency Utils คุณต้องแน่ใจว่าเธรดใหม่ของคุณถูกสร้างขึ้นและจัดการโดยคอนเทนเนอร์ซึ่งรับประกันว่ามีบริการ EE ทั้งหมด

ตัวอย่างที่นี่


2

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

ทำตามกฏ. คุณจะดีใจในบางวันที่คุณทำ :)



2

ไม่มีเหตุผลที่แท้จริงที่จะไม่ทำเช่นนั้น ฉันใช้QuarzกับSpringใน webapp โดยไม่มีปัญหา นอกจากนี้ยังjava.util.concurrentอาจใช้กรอบการทำงานพร้อมกัน หากคุณใช้การจัดการเธรดของคุณเองให้ตั้งค่า theads เป็นdeamonหรือใช้กลุ่มเธรด deamon ของตัวเองเพื่อให้คอนเทนเนอร์ยกเลิกการโหลดเว็บแอปของคุณได้ตลอดเวลา

แต่ระวังเซสชัน bean scopes และคำร้องขอไม่ทำงานในเธรดที่เกิด! นอกจากนี้โค้ดอื่น ๆ ที่กำหนดไว้ThreadLocalก็ไม่สามารถใช้งานได้คุณต้องโอนค่าไปยังเธรดที่สร้างขึ้นด้วยตัวเอง


1

ฉันไม่เคยอ่านว่ามันท้อใจยกเว้นจากข้อเท็จจริงที่ว่ามันไม่ง่ายที่จะทำอย่างถูกต้อง

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


7
มันเป็นสิ่งต้องห้ามตามข้อกำหนด
Ken Liu

1

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.