Остановка потока, который может зацикливаться вечно - PullRequest
4 голосов
/ 22 августа 2011

У меня есть программа, в которой я компилирую код Java, который пользователь вводит в текстовое поле, а затем запускаю его. Выполнение кода в отдельном потоке, чтобы графический интерфейс, который они используют для ввода исходного кода, не блокировался.

В графическом интерфейсе есть кнопка прерывания, которая должна остановить поток. Моя проблема в том, что мне нужно остановить поток компиляции, независимо от того, что происходит внутри него, что означает, что я должен учитывать случай, когда поток пойман в бесконечный цикл (из-за ошибки пользователя), и он не может правильно завершиться сам с помощью безопасного флага. Я читал о многих решениях, которые включают использование какого-либо флага, но они не доступны для меня из-за этой проблемы зацикливания. Мне нужно остановить поток и освободить память, которую он использует (я не могу просто оставить ее на заднем плане, если только это не единственное оставшееся решение). Любой совет или альтернативные решения? Надеемся, что некоторые свежие перспективы помогут решить эту проблему.

Edit:

Вот пример кода, представленного пользователем:

public class RunMe extends SomethingThatRuns {
    public void run() {
        int i = 0;
        while (i = 0) {
            //Prepare to get stuck!
        }
    }
}

Я скомпилирую этот класс, а затем запустите его. Вот где он застрянет, и метод run() никогда не сможет завершиться или даже выполнить цикл для проверки флага.

Ответы [ 6 ]

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

Вызов stop () в потоке.

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

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

Даже этот метод не гарантирует завершение потока.Например, пользователь может поймать полученный Throwable и проигнорировать его.Или реализация потока может не отвечать на вызовы stop(), если поток находится в каком-то нативном коде.Но это твой лучший шанс.

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

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

1 голос
/ 23 августа 2011

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

Я вижу два варианта:

  • Когда вы компилируете код пользователя, вы можете редактировать его раньше. Вы можете использовать ANTLR для разбора и изменения кода.
  • Существуют структуры управления байт-кодом, такие как ASM, которые позволяют вам манипулировать кодом, который уже скомпилирован.

Не думаю, что это легко, но может быть и так.

1 голос
/ 22 августа 2011

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

Правильно ведущие себя потоки обычно должны грациозно завершать себя, когда нет работы (или спокойно возвращаться в пул потоков, чтобы попросить больше работы, если этодизайн вашего приложения).Если вы чувствуете, что вам нужно принудительно убить один поток, тогда у вас, вероятно, есть фундаментальная проблема проектирования.Хорошо, когда один поток сообщает другому: «Эй, теперь вам нужно прекратить, чтобы я мог присоединиться к вам ...» , потому что это позволяет вашим потокам убирать вещи по мере их завершения.Принудительное уничтожение потоков просто не является правильным способом управления этими ситуациями.

0 голосов
/ 22 августа 2011

На высоком уровне вы спрашиваете, как один поток может остановить другой поток. Для этого посмотрите этот SO вопрос Остановка потока в Java? .

0 голосов
/ 22 августа 2011

interupt(); Нить в графическом интерфейсе

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

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