Ich habe Java-Hauptklasse, in der Klasse starte ich einen neuen Thread, in der Hauptklasse wartet er, bis der Thread stirbt. Irgendwann löse ich eine Laufzeitausnahme aus dem Thread, aber ich kann die vom Thread in der Hauptklasse ausgelöste Ausnahme nicht abfangen.
Hier ist der Code:
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)
{
}
}
}
Weiß jemand warum?
java
multithreading
NARU
quelle
quelle
Dies liegt daran, dass Ausnahmen für einen Thread lokal sind und Ihr Hauptthread die
run
Methode nicht sieht . Ich schlage vor, Sie lesen mehr über die Funktionsweise von Threading, aber um es kurz zusammenzufassen: Ihr Aufruf,start
einen anderen Thread zu starten, der völlig unabhängig von Ihrem Haupt-Thread ist. Der Anrufjoin
wartet einfach darauf, dass er erledigt wird. Eine Ausnahme, die in einem Thread ausgelöst und nie abgefangen wird, beendet ihn, weshalb derjoin
Hauptthread zurückgegeben wird, die Ausnahme selbst jedoch verloren geht.Wenn Sie sich dieser nicht erfassten Ausnahmen bewusst sein möchten, können Sie Folgendes versuchen:
Weitere Informationen zur Behandlung nicht erfasster Ausnahmen finden Sie hier .
quelle
Thread.setDefaultUncaughtExceptionHandler()
fängt auch Ausnahmen im Thread "main" abDies erklärt den Zustandsübergang von Threads in Abhängigkeit davon, ob Ausnahmen aufgetreten sind oder nicht:
Quelle: http://www-public.imtbs-tsp.eu/~gibson/Teaching/CSC7322/L8-ExceptionsAndThreads.pdf
quelle
Höchstwahrscheinlich;
Nehmen wir jedoch an, Sie müssen eine Ausnahme von einem untergeordneten Thread eines anderen behandeln. Ich würde einen ExecutorService wie folgt verwenden:
druckt
quelle
future.get()
warten oder blockieren, bis der Thread die Ausführung beendet hat?Bitte werfen Sie einen Blick auf Thread.UncaughtExceptionHandler
Besser (alternativ) ist es, Callable und Future zu verwenden, um das gleiche Ergebnis zu erzielen ...
quelle
Verwenden Sie
Callable
anstelle von Thread, dann können Sie aufrufen,Future#get()
was jede Ausnahme auslöst, die der Callable ausgelöst hat.quelle
Callable.call
in eine eingeschlossen istExcecutionException
und ihre Ursache bewertet werden muss.Derzeit fangen Sie nur
RuntimeException
eine Unterklasse vonException
. Ihre Anwendung kann jedoch andere Unterklassen von Ausnahmen auslösen . Catch GenerikaException
zusätzlich zuRuntimeException
Verwenden Sie die erweiterte Java-API, da viele Dinge im Threading-Bereich geändert wurden.
Bevorzugen Sie die erweiterte java.util.concurrent- API für Multithreading wie
ExecutorService
oderThreadPoolExecutor
.Sie können Ihren ThreadPoolExecutor so anpassen , dass Ausnahmen behandelt werden.
Beispiel von der Oracle-Dokumentationsseite:
Überschreiben
Beispielcode:
Verwendung:
Ich habe einen Konstruktor über dem obigen Code hinzugefügt als:
Sie können diesen Konstruktor an Ihre Anforderungen an die Anzahl der Threads anpassen.
quelle
Ich hatte das gleiche Problem ... wenig Arbeit (nur für die Implementierung, keine anonymen Objekte) ... wir können das Ausnahmeobjekt auf Klassenebene als null deklarieren ... und es dann im catch-Block für die Ausführungsmethode initialisieren ... falls vorhanden war ein Fehler in der Ausführungsmethode, diese Variable wird nicht null sein. Wir können dann eine Nullprüfung für diese bestimmte Variable durchführen lassen. Wenn sie nicht null ist, gab es eine Ausnahme innerhalb der Thread-Ausführung.
Rufen Sie checkForException () nach join () auf.
quelle
Haben Sie mit setDefaultUncaughtExceptionHandler () und den gleichen Methoden der Thread-Klasse herumgespielt? Über die API: "Durch Festlegen des Standard-Handlers für nicht erfasste Ausnahmen kann eine Anwendung die Art und Weise ändern, in der nicht erfasste Ausnahmen behandelt werden (z. B. die Protokollierung auf einem bestimmten Gerät oder einer bestimmten Datei), für diejenigen Threads, die bereits das" Standard "-Verhalten akzeptieren System zur Verfügung gestellt. "
Vielleicht finden Sie dort die Antwort auf Ihr Problem ... viel Glück! :-)
quelle
Auch aus Java 8 können Sie Dan Cruz Antwort schreiben als:
quelle
AtomicReference ist auch eine Lösung, um den Fehler an den Hauptthread zu übergeben. Dies ist der gleiche Ansatz wie der von Dan Cruz.
Die einzige Änderung besteht darin, dass Sie anstelle einer flüchtigen Variablen AtomicReference verwenden können, die hinter den Kulissen dasselbe getan hat.
quelle
Es ist fast immer falsch zu verlängern
Thread
. Ich kann das nicht stark genug sagen.Multithreading-Regel Nr. 1: Das Erweitern
Thread
ist falsch. *Wenn Sie
Runnable
stattdessen implementieren , sehen Sie Ihr erwartetes Verhalten.produziert;
* es sei denn, Sie möchten die Art und Weise ändern, in der Ihre Anwendung Threads verwendet, was in 99,9% der Fälle nicht der Fall ist. Wenn Sie glauben, dass Sie sich in 0,1% der Fälle befinden, lesen Sie bitte Regel 1.
quelle
Wenn Sie Thread.UncaughtExceptionHandler in einer Klasse implementieren, die die Threads startet, können Sie die Ausnahme festlegen und anschließend erneut auslösen:
Was die folgende Ausgabe verursacht:
quelle
Ausnahmebehandlung in Thread: Standardmäßig löst die run () -Methode keine Ausnahme aus, daher müssen alle überprüften Ausnahmen innerhalb der run-Methode nur dort abgefangen und behandelt werden. Für Laufzeitausnahmen können wir UncaughtExceptionHandler verwenden. UncaughtExceptionHandler ist eine von Java bereitgestellte Schnittstelle zur Behandlung von Ausnahmen in einer Thread-Ausführungsmethode. So können wir diese Schnittstelle implementieren und unsere Implementierungsklasse mithilfe der setUncaughtExceptionHandler () -Methode auf das Thread-Objekt zurücksetzen. Dieser Handler muss jedoch gesetzt werden, bevor wir start () auf dem Profil aufrufen.
Wenn wir uncaughtExceptionHandler nicht festlegen, fungiert die Threads ThreadGroup als Handler.
Schöne Erklärung unter http://coder2design.com/thread-creation/#exceptions
quelle
Meine Lösung mit RxJava:
quelle
Für diejenigen, die alle Threads stoppen und erneut ausführen müssen, wenn einer von ihnen aufgrund einer Ausnahme gestoppt wird:
Um zusammenzufassen :
Sie haben eine Hauptfunktion, die mehrere Threads erstellt. Jeder von ihnen verfügt über UncaughtExceptionHandler, der durch eine Ausnahme innerhalb eines Threads ausgelöst wird. Sie fügen jeden Thread einer Liste hinzu. Wenn ein UncaughtExceptionHandler ausgelöst wird, durchläuft er die Liste, stoppt jeden Thread und startet die Neuerstellung der Hauptfunktion für den gesamten Thread neu.
quelle
Sie können dies nicht tun, da es nicht wirklich Sinn macht. Wenn Sie nicht aufgerufen haben, kann sich
t.join()
Ihr Hauptthread an einer beliebigen Stelle im Code befinden, wenn dert
Thread eine Ausnahme auslöst.quelle