Синхронизация части инициализации бесконечно зацикленного сервиса - PullRequest
2 голосов
/ 09 августа 2011

Я пытаюсь реализовать фрагмент кода для синхронного запуска зацикленного сервиса в Java. Идея состоит в том, что код под комментарием // STARTER следует рассматривать как часть метода Service.go(), поэтому, если служба не запускается, я хочу синхронно перезапустить исключение. Этот фрагмент кода должен завершиться только в том случае, если я попытался запустить поток, дождался, пока поток выполнения не достигнет какой-то точки, а затем, если проблем нет, мой метод go() завершается и поток завершается или, если возникли проблемы, я могу повторно выдать исключение, пойманное в методе run() потока, из моего метода go (). Вот решение, которое, кажется, работает нормально, но мне интересно, можно ли сделать его в пару раз короче: -)

public class Program {

private static boolean started;
private static Throwable throwable;

public static void main(String[] args) {
    final Object startedSetterLock = new Object();

    Thread thread = new Thread() {
        public void run() {
            System.out.printf("trying to start...\n");

            boolean ok;
            Throwable t = null;
            try {
                init();
                ok = true;
            } catch(Exception e) {
                ok = false;
                t = e;
            }

            synchronized(startedSetterLock) {
                started = ok;
                throwable = t;
                startedSetterLock.notifyAll();
            }

            if(!ok) {
                return;
            }

            while(true) {
                try {
                    System.out.printf("working...\n");
                    Thread.sleep(1000);
                } catch(InterruptedException e) {
                    System.out.printf("interrupted\n");
                }                   
            }
        }

        private void init() throws Exception { throw new Exception(); } // may throw
    };

            // STARTER
    synchronized(startedSetterLock) {
        thread.start();
        try {           
            startedSetterLock.wait();
        } catch(InterruptedException e) {
            System.out.printf("interrupted\n");
        }
    }       

    // here I'm 100% sure that service has either started or failed to start
    System.out.printf("service started: %b\n", started);
    if(!started) {
        throwable.printStackTrace();
    }
}
}

А также, есть причина , чтобы код инициализации выполнялся в этом потоке, поэтому, пожалуйста, не советуйте запускать код инициализации явно в методе go(), а затем просто передавать все вещи в нить.

Спасибо!

1 Ответ

2 голосов
/ 09 августа 2011

Как насчет переопределения метода Thread.start()?

public static void main(String[] args) {
    Thread t = new Thread() {
        public void run() {
            while (true) {
                try {
                    System.out.printf("working...\n");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    System.out.printf("interrupted\n");
                }
            }
        }

        @Override
        public synchronized void start() {
            try {
                init();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            super.start();
        }

        private void init() throws Exception {
            throw new Exception("test");
        }
    };

    t.start();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...