Обработка исключений в потоке - PullRequest
1 голос
/ 03 февраля 2012

Мы работаем над проектом для управления менеджерами виртуальных машин из приложения Java.

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

Чтобы иметь гладкое приложение, мы хотели иметь CommandManager для обработки разностного запроса к этим гипервизорам в отдельных потоках. Проблема заключается в том, что эти Command могут возвращать определенные ошибки, такие как те, что мы использовали для перехвата в представлении, чтобы отобразить пользователю информацию об этом, но когда мы реализуем Runnable в нашем интерфейсе Commands, мы не можем выбросить любое исключение из этого потока назад, чтобы добраться до вида.

Что я мог сделать, чтобы постоянно уведомлять пользователя об ошибках и их природе?

Извините за мой английский!

Давайте посмотрим код ниже для краткого примера:

Первая команда

class ChangeMemorySize extends Command {
    private String name;
    private int memorySizeMb;

    public ChangeMemorySize(Hypervisor hypervisor, String server,
            String name, int memory) {
        super(hypervisor, server);
        this.name = name;
        this.memorySizeMb = memory;
    }
    protected void execute() throws ConnectionException,OperationException{

    //Some code here

    }
    public void run() //CANT THROW ANYTHING HERE :throws VmConfigFault, 
        try{
            execute();
        }catch{Exception e){
            // I have to catch it all here!
        }

Это не настоящий код, это всего лишь пример. Затем эта команда будет передана менеджеру, который запустит ее в другом потоке. Но я теряю все специфические исключения, которые я использовал, чтобы уведомить пользователя о том, что на самом деле там произошло!

Ответы [ 2 ]

2 голосов
/ 03 февраля 2012

Используйте ExecutorService и выполните одно из двух действий.

Сначала вы можете сохранить все результаты в Future, а когда вы хотите узнать, возникает ли исключение, просто вызовите Future.get () и обработайте любое исключение.

Второй вы можете создать ExecutorService с ThreadFactory, в котором вы установите его как UncaughtExceptionHandler, например

       final UncaughtExceptionHandler handler = new UncaughtExceptionHandler() {
            public void uncaughtException(Thread t, Throwable e) {
                // notify error
            }
        });
        Executor executor = Executors.newFixedThreadPool(1, new ThreadFactory() {
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r);
                thread.setUncaughtExceptionHandler(handler);
                return thread;
            }
        });
1 голос
/ 04 февраля 2012

Хотя я согласен с @John Vint, что ExecutorService с UncaughtExceptionHandler - это хороший подход, если по какой-то причине вы действительно хотите придерживаться Runnables, я бы предложил, чтобы у вашего базового класса, Command, было несколько полей / геттеров для статуса и исключение. например,

Enum Status {FAILED, CANCELLED, SUCCESS};

// protected so subclasses can set them
protected Status status;
protected Exception exception; // null means none

public Status getStatus();
public Exception getException();

Возможно, вы даже захотите добавить поле результата, чтобы действительно имитировать Callable.

Для простоты добавьте метод, который подклассы могут вызывать в предложении catch

protected void s***Happenned(Exception e) {
   this.exception = e;
   status = FAILED;
   // any standard cleanup can go here too...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...