Является ли Java Regex Thread безопасным?

У меня есть функция, которая использует Pattern.compile и Matcher для поиска списка строк для шаблона. Эта функция используется в нескольких потоках. Каждый поток будет иметь уникальный шаблон, переданный шаблону Pattern.compile при создании потока. Количество потоков и шаблонов динамическое, что означает, что во время конфигурации я могу добавить больше шаблонов и потоков.

Нужно ли "синхронизировать" эту функцию, если она использует регулярное выражение? Является ли регулярное выражение в потоке java безопасным?

ТИА

Ответ 1

Да, из документации API Java для Класс шаблона

Экземпляры этого (Pattern) класса неизменяемы и безопасны для использования несколькими параллельными потоками. Экземпляры класса Matcher небезопасны для такого использования.

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

Ответ 2

Безопасность потоков с регулярными выражениями в Java

РЕЗЮМЕ:

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

Вы можете безопасно позвонить Pattern.matcher() на одном шаблоне из разных потоков и безопасно использовать совпадения одновременно. Pattern.matcher() безопасен для создания совпадений без синхронизации. Хотя метод не синхронизируется, внутренне Класс шаблона, изменчивая переменная скомпилированный всегда задается после построение шаблона и чтение на начало вызова совпадения().Это заставляет любой поток ссылаться на Шаблон, чтобы правильно "видеть" содержимое этого объекта.

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

Ответ 3

Хотя вам нужно помнить, что безопасность потока также должна учитывать окружающий код, вам кажется, что вам повезло. Тот факт, что Matchers создаются с использованием шаблона matcher factory и отсутствие общественных конструкторов является положительным знаком. Аналогично, вы используете статический метод compile, чтобы создать охватывающий Pattern.

Итак, словом, если вы делаете что-то вроде примера:

Pattern p = Pattern.compile("a*b");
Matcher m = p.matcher("aaaaab");
boolean b = m.matches();

вы должны делать довольно хорошо.

Последовательность действий над примером кода для ясности: обратите внимание, что этот пример сильно означает, что созданный таким образом Matcher является локальным по потоку с шаблоном и тестом. I.e., вы не должны выставлять Matcher таким образом для любых других потоков.

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

Ответ 4

Быстрый просмотр кода для Matcher.java показывает кучу переменных-членов, включая согласованный текст, массивы для групп, несколько индексов для поддержки местоположения и несколько boolean для другого состояния. Все это указывает на состояние Matcher, которое не будет вести себя хорошо, если будет доступно несколько Threads. Так что JavaDoc:

Экземпляры этого класса небезопасны для использования несколькими параллельными потоки.

Это только проблема, если, как указывает @Bob Cross, вы избегаете своего пути, чтобы разрешить использование Matcher в отдельном Thread s. Если вам нужно это сделать, и вы считаете, что синхронизация будет проблемой для вашего кода, вы можете использовать ThreadLocal объект хранения для поддержания Matcher за рабочий поток.

Ответ 5

Подводя итог, вы можете повторно использовать (хранить в статических переменных) скомпилированные паттерны и сообщать им, чтобы дать вам новые Матчи, когда это необходимо, для проверки этих регулярных выражений против некоторой строки

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Validation helpers
 */
public final class Validators {

private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(\\.[A-Za-z]{2,})$";

private static Pattern email_pattern;

  static {
    email_pattern = Pattern.compile(EMAIL_PATTERN);
  }

  /**
   * Check if e-mail is valid
   */
  public static boolean isValidEmail(String email) { 
    Matcher matcher = email_pattern.matcher(email);
    return matcher.matches();
  }

}

см. http://zoomicon.wordpress.com/2012/06/01/validating-e-mails-using-regular-expressions-in-java/ (ближе к концу) относительно шаблона RegEx, используемого выше для проверки электронной почты (в случае, если он не подходит нужны для проверки электронной почты, поскольку они публикуются здесь)