我正在开发一个J2ME项目,该项目为许多任务(如下载HTTP内容)生成工作线程.基本的线程布局类似于大多数Java应用程序 - 有一个主UI线程和工作线程产生在幕后做的东西.我的问题是处理工作线程中发生的异常的最佳方法是什么?
我通常坚持设计理由,即大多数例外情况应尽可能渗透.当我编写单线程应用程序时,我常常将异常一直渗透到UI层,然后在错误对话框中将它们报告给用户.多线程应用程序是否有类似的做法?对我来说最直观的事情是在Thread.run()中捕获异常,然后在UI线程上调用invokeLater以在对话框中报告它.我在这里看到的问题是,在工作线程之外过早死亡,这种方法并没有真正通知UI线程有错误.我没有看到明确的方法来跨线程抛出异常可以这么说.
谢谢,安迪
您不应该将UI代码堵塞到您的工作人员中!
/** * TWO CHOICES: * - Monitor your threads and report errors, * - setup a callback to do something. */ public class ThreadExceptions { /** Demo of {@link RunnableCatch} */ public static void main(String[] argv) throws InterruptedException { final Runnable bad = new NaughtyThread(); // safe1 doesnt have a callback final RunnableCatch safe1 = new RunnableCatch(bad); // safe2 DOES have a callback final RunnableCatch safe2 = new RunnableCatch(bad, new RunnableCallback() { public void handleException(Runnable runnable, Exception exception) { System.out.println("Callback handled: " + exception.getMessage()); exception.printStackTrace(); } }); final Thread t1 = new Thread(safe1, "myThread"); final Thread t2 = new Thread(safe2, "myThread"); t1.start(); t2.start(); t1.join(); t2.join(); if (safe1.getException() != null) { System.out.println("thread finished with exceptions"); safe1.getException().printStackTrace(); } System.out.println("done"); } } /** Throws an exception 50% of the time */ class NaughtyThread implements Runnable { public void run() { try { if (Math.random() > .5) { throw new RuntimeException("badness"); } } finally { System.out.println("ran"); } } } /** Called when an exception occurs */ interface RunnableCallback { void handleException(Runnable runnable, Exception exception); } /** * Catches exceptions thrown by a Runnable, * so you can check/view them later and/or * deal with them from some callback. */ class RunnableCatch implements Runnable { /** Proxy we will run */ private final Runnable _proxy; /** Callback, if any */ private final RunnableCallback _callback; /** @guarded-by(this) */ private Exception _exception; public RunnableCatch(final Runnable proxy) { this(proxy, null); } public RunnableCatch(final Runnable proxy, RunnableCallback target) { _proxy = proxy; _callback = target; } public void run() { try { _proxy.run(); } catch (Exception e) { synchronized (this) { _exception = e; } if (_callback != null) { _callback.handleException(_proxy, e); } } } /** @return any exception that occured, or NULL */ public synchronized Exception getException() { return _exception; } }