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

后端 未结 2 607
别那么骄傲
别那么骄傲 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;
        }
    }
    

提交回复
热议问题