Создание исключения из абстрактного Runnable.run () в Java - PullRequest
2 голосов
/ 23 апреля 2011

Я создал абстрактный поток, который обрабатывает некоторые потоки в своем методе run (). Мне бы хотелось, чтобы подклассы обрабатывали эти исключения, а не абстрактный родительский класс, но я не знаю, какой самый элегантный способ сделать это. Прямо сейчас я делаю что-то вроде этого:

import org.apache.logging.log4j; // (I use log4j for logging)

public interface Loggable {
     Logger getLogger();
}

public abstract class ParentThread extends Thread implements Loggable {
    private final static Logger logger =
      Logger.getLogger(ParentThread.class); // Logger with no Appenders

    @Override
    public void run() {
        try {
            // Do some stuff that throws exceptions
            doAbstractStuff();
        } catch (SomeSortOfException ex) {
            getLogger().error("Oh noes!", ex);
        } catch (SomeOtherException ex) {
            getLogger().error("The sky is falling!", ex);
        }
    }

    public Logger getLogger() { return logger; }

    protected abstract void doAbstractStuff();
}

public class ChildThread extends ParentThread {

    @Override
    public Logger getLogger() { /* return a logger that I actually use */ }

    @Override
    public void doAbstractStuff() { /* Implementation */ }
}

Полагаю, я должен упомянуть, что ChildThread на самом деле является внутренним классом моей основной формы, и что его регистратор принадлежит этой форме.

Другой подход, о котором я подумал, - это

abstract void handleException(Exception ex);

в ParentThread, но я не могу обработать отдельные исключения из ChildThread.

Ответы [ 3 ]

0 голосов
/ 23 апреля 2011

Ваше первое решение кажется мне концептуально неправильным: смешивание обработки ошибок для конкретного приложения с общей регистрацией.

Ваша вторая идея (обратный вызов) кажется лучшим решением и предлагает возможность абстрагирования от реализации.конкретные исключения для пользовательских событий, например:

public abstract class Parent {

    public void run() {

        InputStream in = null;    
        try {
            in = new URL("bladiebla").openConnection().getInputStream();    
            String text = // ...read text from InputStream     
            if (text == null || text.length() == 0) {
                handleMyEvent(new NoInputEvent());
                return;
            }           
            doWork(text);
        } catch (MalformedURLException e) {
            handleMyEvent(new MyEvent(e));                
        } catch (IOException e) {
            handleMyEvent(new MyEvent(e));
        }
        finally {
            if (in != null) {
                try {
                    in.close();
                }
                catch(IOException e) {
                    handleMyEvent(e);
                }
            }
        }
    }            

    abstract void doWork(String text);

    abstract void handleMyEvent(MyEvent myEvent);
}

public class MyEvent {
    private Exception exception;
    public MyEvent() {}
    public MyEvent(Exception exception) {//set it}
}

public class NoInputEvent extends MyEvent {        
}
0 голосов
/ 23 апреля 2011

Почему в вашем базовом классе есть исключения?Почему бы не использовать то, что предоставляет платформа Thread.setDefaultUncaughtExceptionHandler (UncaughtExceptionHandler eh), и позволить ему делать все что угодно, вместо того, чтобы смешивать ведение журнала с вашим компонентом do-stuff.

0 голосов
/ 23 апреля 2011

Ну, нет никакой разницы между

} catch (SomeSortOfException ex) {
    getLogger().error("Oh noes!", ex);
} catch (SomeOtherException ex) {
    getLogger().error("The sky is falling!", ex);
}

и

if (ex instanceof SomeSortOfException) {
    getLogger().error("Oh noes!", ex);
} else if (ex instanceof SomeOtherException) {
    getLogger().error("The sky is falling!", ex);
}

, хотя последний может потребовать некоторого приведения.

Ваша abstract handleException(Exception ex) идея - это звук, я бы согласился.Я был бы склонен , а не сделать его abstract, однако, и определить разумную реализацию по умолчанию в ParentThread, и позволить ChildThread переопределить его, если требуется.

...