Своеобразное поведение с несколькими потоками / изменчивыми переменными / условиями / циклами (Java) - PullRequest
1 голос
/ 05 января 2011

Вот фрагмент веб-сервера, который я сейчас создаю ...

// ...

threadPool = Executors.newCachedThreadPool();
while (true)
  if(this.isOn) {
                try { // listen for incoming connection
              this.clientSocket = serverSocket.accept();
      } catch (IOException e) {
                   System.err.println("LOG: >> Accept failed! ");
                   System.exit(1);
                  }
      // as soon as a connection is established send the socket
      // with a handler/processor to the thread pool for execution

                    threadPool.execute(new ClientRequestProcessor(clientSocket));
        }

// ...

Обратите внимание, что переменная isOn является логическим значением VOLATILE.

Если я превращу if в какое-то время ... этот код работает ... но как таковой он не работает.Могу я спросить, почему?С логической точки зрения оба должны работать, даже если я проверяю этот флаг в if ... я что-то упустил?!

[Позднее редактирование:] Под неработающим я имею в виду ... браузер (например, firefox) не может подключиться, на самом деле он пытается, но время ожидания истекло.Опять же, если я изменю это, если (isOn) на некоторое время (isOn) это работает как шарм.

Любые предложения / идеи более чем приветствуются !!!

PS Мне нужна эта комбинация«while (true) if / while (test flag) {...}», потому что сервер можно запускать / останавливать из графического интерфейса ... поэтому необходим верхний уровень while (true), поэтому я могу перепроверить,Я включен (и, следовательно, прослушиваю соединения), или если я выключен (и меня не волнуют входящие соединения).Иглы, чтобы сказать, что обработчики событий GUI могут изменить флаг в любое время.

Ответы [ 3 ]

2 голосов
/ 05 января 2011

Лучшее решение - закрыть сокет сервера, когда вы хотите, чтобы он остановился, и запустить новый в новом потоке, когда вы хотите его запустить. Таким образом, вы отклоняете новые подключения и не используете ЦП, когда он ничего не делает.

Когда isOn == true и вы устанавливаете значение false, он не будет принимать соединения после следующего нового соединения. (Может быть в любое время позже) Кроме того, любые новые подключения клиента будут просто ожидать вызова accept (или, в конечном итоге, тайм-аут). Вы можете иметь до 50 подключений, ожидающих принятия по умолчанию.

Когда isOn == false, ваш поток будет занят, ожидая загрузки процессора. Я предлагаю вам поставить небольшую задержку, такую ​​как Thread.sleep (250). Это резко сократит нагрузку на процессор, но не задержит повторный запуск.

Кстати:

  • если вы получили исключение, вы должны войти / распечатать его. Иначе, когда это не удастся, вы не будете знать, почему.
  • Если принять не удалось, это может означать, что в процессе нет файлов, поэтому вы не хотите, чтобы он просто умер, уничтожив все существующие подключения.
0 голосов
/ 05 января 2011

Мое предположение будет основано на вашей тесной петле. Возможно ли, что на вашем сервере запущено несколько экземпляров программы? Версия if (isOn) не будет закрываться, если для isOn задано значение false, вместо этого она будет просто зацикливаться на вечной работе вашего процессора.

0 голосов
/ 05 января 2011

Если у вас есть while (true) и затем if (this.isOn), цикл while не может быть остановлен.Что происходит, когда флаг isOn становится ложным.Цикл while никогда не останавливается, потому что он по существу сделан бесконечным.Подключите оператор else, чтобы он сломался, и он должен работать как положено.

Если вы возьмете оператор if и просто сделаете его в то время (this.isOn), тогда когда флаг isOn установлен в false, циклзаканчивается.Никакой бесконечной петли.

Это мои мысли на первый взгляд ...

...