Java正则expression式线程安全吗?

我有一个函数使用Pattern.compile和一个匹配器来search一个模式的string列表。 这个函数在多个线程中使用。 创build线程时,每个线程将有一个传递给Pattern.compile的唯一模式。 线程和模式的数量是dynamic的,这意味着我可以在configuration期间添加更多的模式和线程。

如果使用正则expression式,我需要在这个函数上放一个“同步”吗? 在java线程安全的正则expression式?

TIA

是的 ,从Pattern类的Java API文档

这个(Pattern)类的实例是不可变的,可以安全地被多个并发线程使用。 Matcher类的实例对于这样的使用是不安全的。

如果您正在查看以性能为中心的代码,请尝试使用reset()方法重置Matcher实例,而不是创build新的实例。 这将重置匹配器实例的状态,使其可用于下一个正则expression式操作。 事实上,Matcher实例中维护的状态是负责并发访问不安全的。

Java中正则expression式的线程安全性

概要:

Java正则expression式API旨在允许在多个匹配操作中共享单个编译模式。

您可以安全地调用Pattern.matcher()从不同的线程相同的模式,并安全地使用匹配器。 Pattern.matcher()是安全的构造匹配器没有同步。 虽然该方法不同步,但在Pattern类的内部,在构造一个模式之后总是设置一个名为compiled的volatilevariables,并在对matcher()的调用开始时读取 这强制任何引用该模式的线程正确“查看”该对象的内容。

另一方面,你不应该在不同的线程之间共享一个匹配器。 或者至less,如果你曾经这样做,你应该使用明确的同步。

虽然你需要记住,线程安全也必须考虑周围的代码,你似乎很幸运。 匹配者是使用模式匹配器工厂方法创build的,缺乏公共构造函数是一个积极的信号。 同样,您使用编译静态方法来创build包含模式 。

所以,总之,如果你做这样的事情:

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

你应该做得很好。

后续的代码示例为了清楚起见:请注意,这个例子强烈地暗示了这样创build的匹配器是模式和testing的线程本地。 也就是说,你不应该将这样创build的Matcher公开给任何其他的线程。

坦率地说,这是任何线程安全问题的风险。 实际情况是,如果你足够努力的话, 任何代码都可能成为线程不安全的。 幸运的是,有很多精彩的 书籍教会了我们可以毁掉我们的代码的一大堆方法。 如果我们远离这些错误,我们大大降低了自己的线程问题的可能性。

快速查看Matcher.java的代码,显示了一堆成员variables,包括正在匹配的文本,组的数组,维护位置的一些索引以及其他状态的一些boolean 。 这一切都指向一个有状态的Matcher ,如果被多个Threads访问,那么这个Matcher就不会很好运行。 JavaDoc也是如此 :

这个类的实例对于多个并发线程是不安全的。

如果像@Bob Cross指出的那样,这只是一个问题,你可以用自己的方式来允许在单独的Thread使用Matcher 。 如果您需要这样做,并且您认为同步将成为您的代码的问题,则您有一个选项是使用ThreadLocal存储对象来维护每个工作线程的Matcher

总结一下,你可以重新使用(保留在静态variables中)编译后的模式,并告诉它们在需要时为你提供新的匹配器来validation这些正则expression式对一些string

 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/ (接近结尾)关于上述用于validation电子邮件的RegEx模式(万一它不符合电子邮件validation的需要,因为它在这里发布)