Как убить непрерывный поток? - PullRequest
2 голосов
/ 02 февраля 2012

Мы проводим соревнование по программированию AI, в котором участники будут кодировать AI, который работает на JVM, используя наш API, который мы им предоставляем.Мы помещаем их в песочницу, ограничивая то, что они могут делать с SecurityManager, и во время выполнения они просто устанавливают несколько флагов, которые являются их решениями.Единственное взаимодействие между нашей системой и их AI происходит через эти флаги, поэтому, если их поток внезапно умрет, у нас не будет плохих последствий.

Когда AI вычисляет слишком долго, мы быхотел бы закрыть свою нить.Тем не менее, мы не можем найти способ гарантировать, что мы уничтожим их поток.Одной из возможных причин этого является то, что AI входит в бесконечный цикл без блокировки, что делает Thread.interrupt() бесполезным.Thread.stop() ненадежен, поскольку, если они находятся в блоке try catch, исключение ThreadDeath будет перехвачено, и у нас нет проблем, потому что они ничего плохого не касаются, и нам все равно, умрут ли они.

В настоящее время мы просто игнорируем их поток и продолжаем без них после истечения времени ожидания, но их бесконечный цикл будет продолжать обработку в фоновом режиме до тех пор, пока JVM не умрет.Это неприемлемо для нас, потому что мы будем запускать матчи в фоновом режиме на веб-сервере 24/7, поэтому мы хотим максимально возможной стабильности.Одна мысль состояла в том, чтобы запустить каждую игру в отдельном JVM, но это намного сложнее, чем мы хотели бы получить.

Есть ли какой-нибудь верный способ уничтожить нить?

Ответы [ 4 ]

0 голосов
/ 28 мая 2012

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

Поскольку у нас не было никакого контроля над кодом, который будет работать в этом случае, и этот код не обязательно был в Java (мы также поддерживали Jython), лучшее решение, которое мы могли придумать, - это создание потока это вошло в цикл, который непрерывно вызывал suspend () и затем stop () в потоке. Результат работал в большинстве случаев, но иногда не мог уничтожить вредоносный поток.

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

http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html#stop%28java.lang.Throwable%29

Передайте пользовательский подкласс Throwable, о котором они не могут знать, и вы можете проверить их код с помощью регулярного выражения: /catch\s*(\s*Throwable/, чтобы убедиться, что они нигде не ловят Throwable.

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

В общем, нет, вы не должны останавливать произвольный поток в JVM (таким образом, методы не рекомендуются).Корень проблемы в том, что вы не знаете, где находится поток, когда вы его уничтожаете.В худшем случае это может быть середина синхронизированного блока в инфраструктуре JVM, которая не готова к непредвиденному исключению, которое будет выдано.(Почти невозможно написать надежный синхронизированный код, который может быть уничтожен исключением в произвольных точках.)

См. Высоко оцененный ответ на этот вопрос для получения более подробной информации: Могут ли серверы приложений Java разрушатьпотоки?Если да, то как?

Возможно, вам удастся сойти с кооперативного дизайна, где вы попросите выход AI.Если это так, то ты в порядке.Если этого не произойдет, необходимо перезапустить JVM.

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

Предоставьте им метод, который они ДОЛЖНЫ вызывать на регулярной основе, даже во время вычислений.Если вы судите, что они «мертвы», заставьте метод спать вечно.Очевидно, что он не будет работать, если они действительно мертвы, но вы должны поймать большинство проблем.

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