Mengapa benang pemijahan di kontainer Java EE tidak disarankan?

120

Salah satu hal pertama yang saya pelajari tentang pengembangan Java EE adalah bahwa saya tidak boleh menelurkan utas saya sendiri di dalam container Java EE. Tetapi ketika saya memikirkannya, saya tidak tahu alasannya.

Dapatkah Anda menjelaskan dengan jelas mengapa hal itu tidak disarankan?

Saya yakin sebagian besar aplikasi perusahaan memerlukan beberapa jenis pekerjaan asinkron seperti daemon email, sesi siaga, pekerjaan pembersihan, dll.

Jadi, jika memang seseorang tidak boleh menelurkan utas, apa cara yang benar untuk melakukannya saat diperlukan?

LiorH
sumber
4
Tugas asinkron biasanya dilakukan menggunakan pesan JMS dan MDB.
Ken Liu
5
Masalah ini akan segera berlalu setelah JSR 236 diimplementasikan di penampung.
letmaik
5
Hal ini tidak disarankan karena utas kedua harus dibuat dan dikelola oleh penampung, sehingga utas akan memiliki akses ke sumber daya perusahaan lainnya. Dengan Java EE7, ada cara standar dan benar untuk membuat utas di lingkungan perusahaan. Dengan menggunakan Concurrency Utils, Anda memastikan bahwa utas baru Anda dibuat, dan dikelola oleh penampung, menjamin bahwa semua layanan EE tersedia. Contoh di sini
Chris Ritchie
Beberapa cara yang benar dalam perspektif JSF / EJB dapat ditemukan di sini: stackoverflow.com/q/6149919
BalusC

Jawaban:

84

Ini tidak disarankan karena semua sumber daya dalam lingkungan dimaksudkan untuk dikelola, dan berpotensi dipantau, oleh server. Selain itu, banyak konteks di mana utas digunakan biasanya dilampirkan ke utas eksekusi itu sendiri. Jika Anda hanya memulai utas Anda sendiri (yang saya yakin beberapa server bahkan tidak akan mengizinkannya), itu tidak dapat mengakses sumber daya lain. Artinya, Anda tidak bisa mendapatkan InitialContext dan melakukan pencarian JNDI untuk mengakses sumber daya sistem lain seperti JMS Connection Factories dan Datasources.

Ada cara untuk melakukan ini "dengan benar", tetapi itu tergantung pada platform yang digunakan.

WorkManager yang umum digunakan untuk WebSphere dan WebLogic serta yang lainnya

Info selengkapnya di sini

Dan di sini

Juga agak menduplikasi yang ini dari pagi ini

PEMBARUAN: Harap perhatikan bahwa pertanyaan dan jawaban ini terkait dengan kondisi Java EE pada tahun 2009, banyak hal telah meningkat sejak saat itu!

Robin
sumber
1
Anda tidak bisa mendapatkan InitialContext dan melakukan pencarian JNDI untuk mengakses sumber daya sistem lain seperti JMS Connection Factories dan Datasources. Saya memiliki aplikasi yang mengatasi masalah ini dengan memasukkan sumber data saat memulai utas, tetapi saya mungkin harus memikirkan kembali pendekatan ini ...
rjohnston
6
Sekarang ada cara standar dan benar untuk membuat utas dengan inti Java EE API. Dengan menggunakan Concurrency Utils, Anda memastikan bahwa utas baru Anda dibuat, dan dikelola oleh penampung, menjamin bahwa semua layanan EE tersedia. Contoh di sini dan di sini
Chris Ritchie
@ChrisRitchie terima kasih atas tipnya. jika hanya JBoss AS / IBM SUDAH mendukung Java EE 7 ... :-(
asgs
1
@asgs WildFly 8 (nama baru untuk JBoss AS) mendukung Java EE 7. IBM hanya sertifikasi
Chris Ritchie
34

Untuk EJB, itu tidak hanya berkecil hati, itu secara tegas dilarang oleh spesifikasinya :

Kacang perusahaan tidak boleh menggunakan primitif sinkronisasi utas untuk menyinkronkan eksekusi beberapa contoh.

dan

Kacang perusahaan tidak boleh mencoba mengelola utas. Kacang perusahaan tidak boleh mencoba untuk memulai, menghentikan, menangguhkan, atau melanjutkan utas, atau mengubah prioritas atau nama utas. Kacang perusahaan tidak boleh mencoba mengelola grup utas.

Alasannya adalah bahwa EJB dimaksudkan untuk beroperasi dalam lingkungan terdistribusi. EJB mungkin dipindahkan dari satu mesin dalam cluster ke cluster lainnya. Benang (dan soket serta fasilitas terbatas lainnya) merupakan penghalang signifikan untuk portabilitas ini.

Dan Dyer
sumber
3
Java EE7 Concurrency Utils menyediakan cara yang benar untuk membuat thread di lingkungan perusahaan. Contoh di sini dan di sini
Chris Ritchie
1
@Dan Bisakah Anda menjelaskan kepada saya mengapa Thread akan menjadi penghalang yang signifikan terhadap portabilitas pemindahan EJB dari satu mesin di custer ke yang lain?
Geek
13

Alasan Anda tidak boleh menelurkan utas Anda sendiri adalah karena ini tidak akan dikelola oleh penampung. Kontainer menangani banyak hal yang sulit dibayangkan oleh pengembang pemula. Misalnya hal-hal seperti penggabungan thread, pengelompokan, pemulihan kerusakan dilakukan oleh penampung. Saat Anda memulai utas, Anda mungkin kehilangan beberapa di antaranya. Kontainer juga memungkinkan Anda memulai ulang aplikasi tanpa memengaruhi JVM tempat menjalankannya. Bagaimana ini mungkin terjadi jika ada utas di luar kendali wadah?

Ini alasan bahwa dari layanan timer J2EE 1.4 diperkenalkan. Lihat artikel ini untuk detailnya.

kgiannakakis
sumber
2
JSR 236 menambahkan fitur untuk mendukung utas pemijahan di Java EE 7 dan yang lebih baru. Lihat saudara kandung ini Jawaban oleh Chris Ritchie .
Basil Bourque
8

Utilitas Concurrency untuk Java EE

Sekarang ada cara standar dan benar untuk membuat utas dengan inti Java EE API:

Dengan menggunakan Concurrency Utils, Anda memastikan bahwa utas baru Anda dibuat, dan dikelola oleh penampung, menjamin bahwa semua layanan EE tersedia.

Contohnya disini

Chris Ritchie
sumber
2

Anda selalu dapat memberi tahu container untuk memulai sesuatu sebagai bagian dari deskriptor penerapan Anda. Ini kemudian dapat melakukan tugas pemeliharaan apa pun yang perlu Anda lakukan.

Ikuti aturan. Anda akan senang suatu hari Anda melakukannya :)

Thorbjørn Ravn Andersen
sumber
2

Benang dilarang dalam wadah Java EE sesuai dengan cetak biru. Silakan lihat cetak biru untuk informasi lebih lanjut.

Ojitha
sumber
2

Tidak ada alasan nyata untuk tidak melakukannya. Saya menggunakan Quarz dengan Spring di aplikasi web tanpa masalah. Juga kerangka konkurensi java.util.concurrentdapat digunakan. Jika Anda menerapkan penanganan utas Anda sendiri, setel theads ke deamon atau gunakan grup utas deamon sendiri untuk mereka sehingga penampung dapat membongkar aplikasi web Anda kapan saja.

Tapi hati-hati, sesi dan permintaan cakupan kacang tidak berfungsi di utas yang muncul! Juga kode lain yang didasarkan pada ThreadLocaltidak berfungsi di luar kotak, Anda perlu mentransfer nilai ke utas yang muncul sendiri.

Arne Burmeister
sumber
1

Saya tidak pernah membaca bahwa itu berkecil hati, kecuali dari kenyataan bahwa itu tidak mudah dilakukan dengan benar.

Ini adalah pemrograman tingkat rendah, dan seperti teknik tingkat rendah lainnya, Anda harus memiliki alasan yang bagus. Sebagian besar masalah konkurensi dapat diselesaikan jauh lebih efektif menggunakan konstruksi bawaan seperti kumpulan utas.

levand
sumber
7
itu memang dilarang oleh spesifikasi.
Ken Liu
1

Salah satu alasan saya menemukan jika Anda menelurkan beberapa utas di Anda EJB dan kemudian Anda mencoba untuk membongkar kontainer atau memperbarui EJB Anda, Anda akan mengalami masalah. Hampir selalu ada cara lain untuk melakukan sesuatu di mana Anda tidak memerlukan Thread, jadi katakan saja TIDAK.

Javamann
sumber