我有一个Java main类,在这个类中,我启动一个新线程,在main中,它等待线程死亡。在某个时刻,我从线程抛出运行时异常,但我无法捕获从主类中的线程抛出的异常。
代码如下:
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)
{
}
}
}
有人知道为什么吗?
扩展Thread几乎总是错误的。我怎么强调都不为过。
多线程规则1:扩展线程是错误的
如果您实现Runnable,您将看到您预期的行为。
public class Test implements Runnable {
public static void main(String[] args) {
Test t = new Test();
try {
new Thread(t).start();
} 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");
Thread.sleep(2000);
throw new RuntimeException("exception from thread");
}
} catch (RuntimeException e) {
System.out.println("** RuntimeException from thread");
throw e;
} catch (InterruptedException e) {
}
}
}
产生;
Main stoped
** Started
** RuntimeException from threadException in thread "Thread-0" java.lang.RuntimeException: exception from thread
at Test.run(Test.java:23)
at java.lang.Thread.run(Thread.java:619)
除非你想改变你的应用程序使用线程的方式,在99.9%的情况下你不会这样做。如果你认为你属于0.1%的情况,请参阅规则1。
最有可能的;
您不需要将异常从一个线程传递到另一个线程。
如果你想处理异常,只需在抛出异常的线程中处理即可。
在本例中,主线程不需要从后台线程等待,这实际上意味着您根本不需要后台线程。
但是,让我们假设您确实需要处理来自子线程的异常。我将像这样使用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");
打印
** 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