Является ли 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, используемого выше для проверки электронной почты (в случае, если он не подходит нужны для проверки электронной почты, поскольку они публикуются здесь)