在Thread.run中处理java异常

时间:2016-05-04 20:08:21

标签: java exception-handling

我有一个扩展Thread

的内部类
private class TestStart extends Thread {
    public void run() {
        try {
            startServer();
        }
        catch (Exception e) {
            /// How to handle it?
        }
    }
} 

主线程中的调用者:

public void start() throws Exception {
    Thread st = new TestStart();
    st.start();
}

方法startServer()通过其API抛出Exception,因此我必须使用try-catch,因为Thread.run()不会在方法定义中“抛出”异常。我需要将捕获的异常冒泡到主线程中来处理它。有一个简单的方法吗?感谢

3 个答案:

答案 0 :(得分:3)

如果使用ExecutorService而不是使用原始线程,则可以通知您未捕获的异常:

class MyCallable implements Callable<Void> {
  @Override public Void call() throws Exception {
    // Do something - you don't need to catch Exception as Callable throws it.
    // ...

    return null;  // A return is necessary from a Callable.
  }
}

在某处创建执行服务,例如:

ExecutorService executor = Executors.newFixedThreadPool(1);

然后,在启动线程的代码中:

Future<?> future = executor.submit(new MyCallable());

try {
  future.get();  // Blocks until the Callable completes.
} catch (ExecutionException e) {
  // You reach here if an exception is thrown in the Callable -
  // The exception is accessible via e.getCause().
}

答案 1 :(得分:0)

在你的线程上设置一个新的异常处理程序。

   st.setDefaultUncaughtExceptionHandler(new Thread.
             UncaughtExceptionHandler() {
               public void uncaughtException(Thread t, Throwable e) {
               System.out.println(t + " throws exception: " + e);
             }
   });

将该代码放在start()之前;

答案 2 :(得分:0)

有一些可能的解决方案。例如:

  1. 使用setUncaughtExceptionHandler()/ setDefaultUncaughtExceptionHandler()并更改你的try / catch

    try {
        startServer();
    }
    catch (RuntimeException e) {
        throw e;
    }
    catch (Exception e) {
        throw new RuntimeException(e);
    }
    
  2. 或使用自定义侦听器

    private class TestStart extends Thread {
        private final ServerStateListener lnr;
    
        TestStart(ServerStateListener lnr) {
            this.lnr = lnr;
        }
    
        public void run() {
            try {
                startServer();
                lnr.onServerStarted();
            }
            catch (Exception e) {
                lnr.onServerStoppedByError(e);
            }
        }
    }
    
  3. 或者只是保存Exception并在.join

    之后阅读
    private class TestStart extends Thread {
        private Exception error; // if you start and join and read this property within one thread, you don't need to use volatile, otherwise do it for safe publication
    
        public void run() {
            try {
                startServer();
            }
            catch (Exception e) {
                error = e;
            }
        }
    
        public Exception getError() {
            return error;
        }
    } 
    
  4. 或者使用ExecutorService / Callable代替您自己的线程,正如Andy建议的那样。