Java - как остановить поток, выполняющий произвольный код? - PullRequest
0 голосов
/ 07 марта 2011

В моем приложении, которое запускает представленный пользователем код [1] в отдельных потоках, могут быть некоторые случаи, когда выполнение кода может занять очень много времени или даже может иметь бесконечный цикл! В таком случае, как мне остановить этот конкретный поток?

Я не контролирую пользовательский код, поэтому не могу проверить наличие Thread.interrupted () изнутри. Также я не могу использовать Thread.stop () небрежно. Я также не могу поместить этот код в отдельные процессы.

Итак, есть ли способ справиться с этой ситуацией?

[1] Я использую JRuby, а код пользователя в ruby.

Ответы [ 4 ]

4 голосов
/ 07 марта 2011

С учетом предоставленных вами ограничений:

  1. Пользовательский код, который вы не можете контролировать.
  2. Невозможно принудительно выполнить проверки для Thread.interrupted().
  3. Невозможно использовать Thread.stop().
  4. Невозможно поместить код пользователя в тюрьму процесса.

Ответ на ваш вопрос: «Нет, нет способа справиться с этой ситуацией». Вы в значительной степени систематически проектировали вещи, чтобы у вас был нулевой контроль над ненадежным сторонним кодом. Это ... неоптимальный дизайн.

Если вы хотите быть в состоянии справиться с чем-либо, вам придется ослабить одно (или предпочтительно больше!) Из вышеуказанных ограничений.


Отредактировано, чтобы добавить:

Может быть, вы можете обойти это, не заставляя своих клиентов менять код, если это (другое) ограничение. Запустите код Ruby в другом процессе и используйте какой-либо механизм IPC для взаимодействия с вашей основной кодовой базой. Чтобы избежать принудительного кодирования Ruby-кода для использования явного IPC, добавьте набор прокси-объектов для вашего API, которые выполняют IPC за кулисами, которые сами вызывают прокси-объекты на вашем собственном сервере. Таким образом, ваш клиентский код получает иллюзию работы внутри вашего сервера, в то время как вы заключаете этот код в тюрьму в своем собственном процессе (что в конечном итоге вы можете kill -9 в качестве окончательного разрешения, если оно придет к этому).

Позже вы захотите отучить своих клиентов от иллюзии, поскольку IPC и нативные вызовы сильно отличаются и скрывают, что за прокси-сервером может быть зло, но это временная задержка, которую вы можете использовать, пока вы устареть API и перенести своих клиентов на новые API.

1 голос
/ 07 марта 2011

Я не уверен насчет угла Ruby (или угла потоков) здесь, но если вы запускаете пользовательский код, вам лучше запустить его в отдельном процессе, а не в отдельном потоке тот же процесс.

Правило номер один: никогда не доверяйте пользовательскому вводу. Гораздо меньше, если ввод кода!

Приветствия

0 голосов
/ 07 марта 2011

Для запуска потока Thread.Interrupt фактически не остановится, как sfussenegger упоминается после (спасибо sfussenegger, вспомнил после прочтения спецификации).

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

private boolean isExit= false;

public void beforeExit() {
    isExit= true;
}

public void run() {
    while (!isExit) {

    }
}
0 голосов
/ 07 марта 2011

Обычно у вас есть переменная для указания остановки потока. Затем какой-то другой поток установит для этой переменной значение true. Наконец, вы периодически проверяете, установлена ​​переменная или нет.

Но, учитывая, что вы не можете изменить код пользователя, Боюсь, нет безопасного способа сделать это .

...