Как установить ограничение по времени на функции Java выполнение regex

Вероятно, было бы легче просто использовать Для цикла вместо ForEach. Но, точно так же Вы могли сохранить счетчик в своем Цикле foreach и видеть, если его равное yourCollection.Count - 1, то Вы находитесь в последнем повторении.

5
задан Fábio Nascimento 27 June 2019 в 16:14
поделиться

7 ответов

То, что вы сделали, мне нравится, вот как я измените его:

final AtomicReference<String> resultXml = new AtomicReference<String>();

RegexpThread rt = new RegexpThread() {
  public void run() {
    method2(m, urlCopy, document, resultXml);
  }

};

rt.start();

try {
    rt.join(6 * 1000);
} catch (InterruptedException e) {
    return "y";
}

if(resultXml.get() == null) {
    rt.interupt();
    return "g";
}

resultXml.append(resultXml.get());

return resultXml.toString();
-2
ответ дан 13 December 2019 в 22:12
поделиться

Я могу ошибаться здесь, но я думаю, что все способы завершить поток уже давно устарели . Рекомендуемый способ - использовать общую переменную isRunning , которую ваш рабочий поток периодически проверяет и корректно завершает, когда она установлена.

Это не сработает в вашем случае, но мне кажется, что вы лечение симптома - не настоящая проблема. Вы должны опубликовать код своей функции регулярного выражения, выполнение которой занимает 6 секунд. Если это само регулярное выражение,

9
ответ дан 13 December 2019 в 22:12
поделиться

Есть два способа ответить на этот вопрос.

С одной стороны, не существует известного практического / эффективного способа, который, как известно, был бы безопасным для остановки выполняемого потока Matcher.find (...) или Matcher.match (...) . Вызов Thread.stop () будет работать, но есть серьезные проблемы с безопасностью. Единственный способ решить эту проблему - разработать собственный механизм регулярных выражений, который регулярно проверял бы флаг прерванный . (Это не совсем непрактично. Например, если GPL не проблема для вас, вы можете начать с существующего механизма регулярных выражений в OpenJDK.)

С другой стороны, настоящий корень вашей проблемы (скорее всего, ), что вы неправильно используете регулярные выражения. Либо вы пытаетесь сделать что-то слишком сложное для одного регулярного выражения, или ваше регулярное выражение неоптимально.

РЕДАКТИРОВАТЬ : Типичная причина того, что регулярные выражения занимают слишком много времени, - это множественные кванторы (?, , +), вызывающие патологический возврат. Например, если вы попытаетесь сопоставить строку из N символов «A», за которой следует «B», с регулярным выражением «^ A A A A A A $» , сложность вычисления (не менее) O (N ** 5). Вот более «реальный» пример:

"(.*)<html>(.*)<head>(.*)</head>(.*)<body>(.*)</body>(.*)</html>(.*)"

А теперь представьте, что произойдет, если вы встретите такую ​​«веб-страницу»:

<html><html><html><html><html><html><html><html><html><html>
<head><head><head><head><head><head><head><head><head><head>
</head></head></head></head></head></head></head></head></head></head>
<body><body><body><body><body><body><body><body><body><body><body>
</body></body></body></body></body></body></body></body></body></body>

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

В этом случае,

2
ответ дан 13 December 2019 в 22:12
поделиться

Запустите свой поток через ExecutorService и дайте ему тайм-аут, например:

ExecutorService pool = Executors.newFixedThreadPool(POOL_SIZE);
pool.execute(rt);
pool.awaitTermination(timeout, timeUnit);

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

Похоже, это соответствует вашим потребностям.

0
ответ дан 13 December 2019 в 22:12
поделиться

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

Если это В этом случае лучшим решением будет передать этой функции значение тайм-аута. После каждых N строк (какими бы N могло быть) он проверяет значение тайм-аута.

Настоящая проблема, с которой вы столкнетесь, связана с блокировкой ввода-вывода - например, чтение из сети. В этом случае вы ничего не сможете сделать с Java, поскольку блокировка фактически происходит в ядре ОС.

0
ответ дан 13 December 2019 в 22:12
поделиться

Класс Java Thread не приспособлен для обработки такого рода прерываний и поэтому не подходит для ваших требований.

Я бы реализовал функциональность в отдельный процесс с использованием ProcessBuilder и использование потоков ввода и вывода, предоставленных классом Process для связи. Принудительное прерывание обеспечивается методом destroy класса Process .

Я считаю, что это правильная и самая безопасная реализация для ваших требований. К сожалению, Java не позволяет легко запускать другой процесс Java независимо от платформы, поэтому вам придется иметь исполняемый файл java на своем пути и создать для этого отдельный метод main . Это сложнее, чем должно быть.

0
ответ дан 13 December 2019 в 22:12
поделиться

На данный момент я предполагаю, что ваш код регулярного выражения правильный, и на самом деле это некоторый вычислительный код, привязанный к ЦП на 6 секунд.

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

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

Вы не можете делают это:

  1. с помощью Thread.stop () и т. Д. Это устарело и работает неправильно.
  2. Использование Thread.interrupt () . Это устанавливает флаг прерывания в потоке, который проверяется только тогда, когда поток выполняет ввод-вывод. Если поток привязан к процессору, то этот флаг никогда не будет проверяться.

Учитывая вышесказанное, я хотел бы еще раз посмотреть, почему регулярное выражение требует 6 секунд для сопоставления. Регулярное выражение правильное? Можете ли вы выполнить регулярное выражение для небольших текстовых сегментов?

2
ответ дан 13 December 2019 в 22:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: