Java: разрешить рабочему потоку убивать основной поток

Я пишу простой HTTP-сервер, в котором основной поток зацикливается в цикле ServerSocket.accept и передает любые входящие сокеты рабочим потокам, которые затем обрабатывают их и отправляют ответы. Тем не менее, я хочу, чтобы в особом случае запрос на выключение отключил весь мой сервер. У меня возникли проблемы с использованием рабочего потока, чтобы заставить основной поток выйти из цикла accept и завершить его.

Любые указатели?


person Jin    schedule 26.01.2013    source источник


Ответы (3)


как упоминалось в этом потоке, вы можете просто вызвать close() на сокете сервера, что приведет к исключению в вызове accept.

person cybye    schedule 26.01.2013
comment
Ах, грязно, но, вероятно, самое чистое и простое в обращении из всех возможных решений. Спасибо! - person Jin; 27.01.2013

Вы пытались прервать рабочий поток с помощью workerThread.interrupt();?

Это должно заставить accept бросить InterruptedException, который вы можете поймать, очистить то, что нужно очистить, и выйти из рабочего потока.

person assylias    schedule 26.01.2013
comment
Ах, но я хочу прервать основной поток, который застрял в принятии вызова. У меня есть доступ ко всем рабочим потокам, и у меня есть флаги в рабочих потоках, чтобы при необходимости завершать их. Спасибо за ответ! - person Jin; 27.01.2013

Вы, вероятно, можете придумать 100 хакерских способов сделать это, но я вижу только два способа в правильно спроектированном приложении.

  1. Это перерыв в обработке кода.

    while (acceptNextRequest()) {
        // Processing code
        if (shouldExitNow()) {
            break;
        }
        // More processing
    }
    // Proper exiting code
    
  2. Проверьте, не пора ли выйти, прежде чем принимать следующий запрос:

    while (!shouldExitBeforeNextRequest() && acceptNextRequest()) {
        // Processing code
    }
    // Proper exiting code
    

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

Если вы выполните System.exit() из веб-приложения, вы закроете все приложение веб-сервера (Tomcat, JBoss или что-то еще), что обычно не то, что вы хотите делать из своего приложения.

И не связывайтесь с основным потоком, если вы запускаете приложение в контейнере.

person ATrubka    schedule 26.01.2013
comment
Да, единственная проблема с проверкой заключается в том, что ServerSocket уже принимает вызов, поэтому он не может проверить операторы условий. System.exit() потенциально работает... немного некрасиво, ха-ха. Спасибо! - person Jin; 27.01.2013
comment
Это нормально. Все зависит от фактического исходящего кода. На самом деле, веб-приложения никогда не должны быть закрыты. Вы можете выйти из веб-приложения, очистить его состояние, но вы никогда не должны делать его недоступным для будущих запросов. - person ATrubka; 27.01.2013
comment
Я еще не видел пользовательских требований, требующих выхода из веб-приложения. Это больше похоже на быстрый взлом, чтобы не развивать его должным образом. - person ATrubka; 27.01.2013