What is the best approach to handling exceptions thrown in a separate thread?

后端 未结 2 591
别那么骄傲
别那么骄傲 2020-12-30 17:12

I am working on a J2ME project that spawns worker threads for numerous tasks such as downloading HTTP content. The basic thread layout is similar to most java apps--there is

相关标签:
2条回答
  • 2020-12-30 17:42

    You should NOT jam UI code into your workers!

    /**
     * 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;
        }
    }
    
    0 讨论(0)
  • 2020-12-30 17:42

    Another option other than what Stuph has given is to set exceptions in the thread local. If another exception happens before that exception is cleared then an assert occurs. That at least gives someone a chance to notice the exception and process it.

    0 讨论(0)
提交回复
热议问题