NAR*_*ARU 153 java multithreading
我有Java主类,在类中,我启动一个新线程,在主,它等待直到线程死亡.在某些时刻,我从线程中抛出一个运行时异常,但是我无法捕获从主类中的线程抛出的异常.
这是代码:
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)
{
}
}
}
Run Code Online (Sandbox Code Playgroud)
谁知道为什么?
Dan*_*ruz 206
用一个Thread.UncaughtExceptionHandler
.
Thread.UncaughtExceptionHandler h = new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread th, Throwable ex) {
System.out.println("Uncaught exception: " + ex);
}
};
Thread t = new Thread() {
public void run() {
System.out.println("Sleeping ...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Interrupted.");
}
System.out.println("Throwing exception ...");
throw new RuntimeException();
}
};
t.setUncaughtExceptionHandler(h);
t.start();
Run Code Online (Sandbox Code Playgroud)
aby*_*byx 37
那是因为异常是一个线程的本地,而你的主线程实际上并没有看到该run
方法.我建议你阅读更多有关线程如何工作的内容,但要快速总结一下:你的调用start
启动一个不同的线程,完全与你的主线程无关.调用join
只是等待它完成.在线程中抛出并且永远不会被捕获的异常终止它,这就是为什么join
在主线程上返回,但异常本身会丢失.
如果您想了解这些未捕获的异常,可以尝试这样做:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("Caught " + e);
}
});
Run Code Online (Sandbox Code Playgroud)
有关未捕获的异常处理的更多信息,请参见此处.
Pet*_*rey 20
最有可能的;
但是,假设您确实需要从另一个子线程处理异常.我会像这样使用ExecutorService:
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Void> future = executor.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
System.out.println("** Started");
Thread.sleep(2000);
throw new IllegalStateException("exception from thread");
}
});
try {
future.get(); // raises ExecutionException for any uncaught exception in child
} catch (ExecutionException e) {
System.out.println("** RuntimeException from thread ");
e.getCause().printStackTrace(System.out);
}
executor.shutdown();
System.out.println("** Main stopped");
Run Code Online (Sandbox Code Playgroud)
版画
** Started
** RuntimeException from thread
java.lang.IllegalStateException: exception from thread
at Main$1.call(Main.java:11)
at Main$1.call(Main.java:6)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
** Main stopped
Run Code Online (Sandbox Code Playgroud)
使用Callable
而不是 Thread,那么您可以调用Future#get()
它抛出 Callable 抛出的任何异常。
AtomicReference 也是一种将错误传递给主线程的解决方案。与 Dan Cruz 的方法相同。
AtomicReference<Throwable> errorReference = new AtomicReference<>();
Thread thread = new Thread() {
public void run() {
throw new RuntimeException("TEST EXCEPTION");
}
};
thread.setUncaughtExceptionHandler((th, ex) -> {
errorReference.set(ex);
});
thread.start();
thread.join();
Throwable newThreadError= errorReference.get();
if (newThreadError!= null) {
throw newThreadError;
}
Run Code Online (Sandbox Code Playgroud)
唯一的变化是,您可以使用 AtomicReference,而不是创建 volatile 变量,它在幕后做了同样的事情。
归档时间: |
|
查看次数: |
162928 次 |
最近记录: |