Saya memiliki kelas utama Java, di kelas, saya memulai utas baru, di utas, menunggu sampai utas mati. Pada suatu saat, saya melempar pengecualian runtime dari utas, tetapi saya tidak dapat menangkap pengecualian yang dilemparkan dari utas di kelas utama.
Ini kodenya:
public class Test extends Thread
{
public static void main(String[] args) throws InterruptedException
{
Test t = new Test();
try
{
t.start();
t.join();
}
catch(RuntimeException e)
{
System.out.println("** RuntimeException from main");
}
System.out.println("Main stoped");
}
@Override
public void run()
{
try
{
while(true)
{
System.out.println("** Started");
sleep(2000);
throw new RuntimeException("exception from thread");
}
}
catch (RuntimeException e)
{
System.out.println("** RuntimeException from thread");
throw e;
}
catch (InterruptedException e)
{
}
}
}
Adakah yang tahu mengapa?
java
multithreading
NARU
sumber
sumber
Itu karena pengecualian bersifat lokal untuk utas, dan utas utama Anda sebenarnya tidak melihat
run
metodenya. Saya sarankan Anda membaca lebih lanjut tentang cara kerja threading, tetapi untuk meringkas dengan cepat: panggilan Anda untukstart
memulai utas yang berbeda, sama sekali tidak terkait dengan utas utama Anda. Panggilan untukjoin
hanya menunggu untuk dilakukan. Pengecualian yang dilemparkan ke utas dan tidak pernah tertangkap akan menghentikannya, itulah sebabnyajoin
kembali ke utas utama Anda, tetapi pengecualian itu sendiri hilang.Jika Anda ingin mengetahui pengecualian yang tidak tertangkap ini, Anda dapat mencoba ini:
Informasi lebih lanjut tentang penanganan pengecualian tanpa tertangkap dapat ditemukan di sini .
sumber
Thread.setDefaultUncaughtExceptionHandler()
juga menangkap pengecualian di utas "utama"Ini menjelaskan transisi status utas yang bergantung pada apakah pengecualian terjadi atau tidak:
Sumber: http://www-public.imtbs-tsp.eu/~gibson/Teaching/CSC7322/L8-ExceptionsAndThreads.pdf
sumber
Yang paling disukai;
Namun, anggaplah Anda memang perlu menangani pengecualian dari utas anak lainnya. Saya akan menggunakan ExecutorService seperti ini:
cetakan
sumber
future.get()
menunggu atau memblokir sampai utas telah selesai dieksekusi?Silakan lihat Thread.UncaughtExceptionHandler
Cara (alternatif) yang lebih baik adalah menggunakan Callable dan Future untuk mendapatkan hasil yang sama ...
sumber
Gunakan
Callable
sebagai ganti Thread, maka Anda bisa meneleponFuture#get()
yang melempar pengecualian yang dilontarkan Callable.sumber
Callable.call
dibungkus denganExcecutionException
dan penyebabnya harus dievaluasi.Saat ini Anda hanya menangkap
RuntimeException
, sub kelas dariException
. Tetapi aplikasi Anda dapat membuang sub-kelas Pengecualian lainnya .Exception
Selain generikRuntimeException
Karena banyak hal telah diubah di bagian depan Threading, gunakan API java lanjutan.
Lebih memilih muka java.util.concurrent API untuk multi-threading seperti
ExecutorService
atauThreadPoolExecutor
.Anda dapat menyesuaikan ThreadPoolExecutor Anda untuk menangani pengecualian.
Contoh dari halaman dokumentasi oracle:
Mengesampingkan
Kode contoh:
Pemakaian:
Saya telah menambahkan satu konstruktor di atas kode di atas sebagai:
Anda dapat mengubah konstruktor ini agar sesuai dengan kebutuhan Anda pada jumlah utas.
sumber
Saya menghadapi masalah yang sama ... sedikit kerja di sekitar (hanya untuk implementasi bukan objek anonim) ... kita dapat mendeklarasikan objek pengecualian tingkat kelas sebagai null ... lalu inisialisasi di dalam blok tangkap untuk menjalankan metode ... jika ada adalah kesalahan dalam menjalankan metode, variabel ini tidak akan menjadi nol .. kita kemudian dapat memiliki pemeriksaan nol untuk variabel tertentu ini dan jika tidak nol maka ada pengecualian di dalam eksekusi thread.
panggil checkForException () setelah bergabung ()
sumber
Apakah Anda bermain-main dengan setDefaultUncaughtExceptionHandler () dan metode serupa dari kelas Thread? Dari API: "Dengan menetapkan penangan pengecualian tanpa tertangkap default, aplikasi dapat mengubah cara penanganan pengecualian tanpa penangkapan (seperti masuk ke perangkat tertentu, atau file) untuk utas yang sudah menerima perilaku" default "apa pun yang sistem disediakan. "
Anda mungkin menemukan jawaban untuk masalah Anda di sana ... semoga berhasil! :-)
sumber
Juga dari Java 8 Anda dapat menulis jawaban Dan Cruz sebagai:
sumber
AtomicReference juga merupakan solusi untuk meneruskan kesalahan ke utas utama. Pendekatan yang sama seperti yang dilakukan Dan Cruz.
Satu-satunya perubahan adalah bahwa alih-alih membuat variabel volatil Anda dapat menggunakan AtomicReference yang melakukan hal yang sama di belakang layar.
sumber
Hampir selalu salah untuk memperpanjang
Thread
. Saya tidak bisa menyatakan ini dengan cukup kuat.Aturan Multithreading # 1: Memperluas
Thread
itu salah. *Jika Anda menerapkannya,
Runnable
Anda akan melihat perilaku yang Anda harapkan.menghasilkan;
* kecuali jika Anda ingin mengubah cara aplikasi Anda menggunakan utas, yang dalam 99,9% kasus Anda tidak. Jika menurut Anda Anda berada dalam 0,1% kasus, lihat aturan # 1.
sumber
Jika Anda menerapkan Thread.UncaughtExceptionHandler di kelas yang memulai Threads, Anda bisa mengatur dan kemudian menyusun kembali pengecualian:
Yang menyebabkan output berikut:
sumber
Penanganan pengecualian di Thread: Secara default metode run () tidak membuang pengecualian, jadi semua pengecualian yang diperiksa di dalam metode run harus ditangkap dan ditangani di sana saja dan untuk pengecualian runtime kita bisa menggunakan UncaughtExceptionHandler. UncaughtExceptionHandler adalah antarmuka yang disediakan oleh Java untuk menangani pengecualian dalam metode Thread run. Jadi kita bisa mengimplementasikan antarmuka ini dan mengatur kembali kelas implementasi kita ke objek Thread menggunakan metode setUncaughtExceptionHandler (). Tetapi pawang ini harus diatur sebelum kita memanggil start () pada tapak.
jika kita tidak menyetel uncaughtExceptionHandler maka Threads ThreadGroup bertindak sebagai penangan.
Penjelasan bagus diberikan di http://coder2design.com/thread-creation/#exceptions
sumber
Solusi saya dengan RxJava:
sumber
Bagi mereka yang perlu menghentikan semua Threads menjalankan dan menjalankan kembali semuanya ketika salah satu dari mereka dihentikan pada Pengecualian:
Untuk menyimpulkan :
Anda memiliki fungsi utama yang membuat banyak utas, masing-masing memiliki UncaughtExceptionHandler yang dipicu oleh setiap pengecualian dalam utas. Anda menambahkan setiap Thread ke Daftar. Jika UncaughtExceptionHandler dipicu itu akan berulang melalui Daftar, hentikan setiap Thread dan meluncurkan kembali fungsi utama rekreasi semua Thread.
sumber
Anda tidak dapat melakukan ini, karena itu tidak masuk akal. Jika Anda belum menelepon
t.join()
maka utas utama Anda bisa berada di mana saja dalam kode ketikat
utas membuat pengecualian.sumber