【问题标题】:Is Pattern::asPredicate thread safePattern::asPredicate 线程是否安全
【发布时间】:2019-11-21 22:17:39
【问题描述】:

我查看了 java 8 文档,发现 Pattern 类有 asPredicate 方法。

我正在查看 StackOverflow,但没有找到任何与线程安全相关的内容。

我知道 Pattern 类正如文档所说的那样是线程安全的

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

但是,asPredicate 方法生成的 Predicate 会发生什么?

【问题讨论】:

  • 一个谓词只提供一个值。它没有可以更改的状态。所以它是不可变的,因此是线程安全的。
  • 线程安全大多没有记录。但这可能会有所帮助:stackoverflow.com/questions/1360113/is-java-regex-thread-safe
  • @Eugene 好吧。如果asPredicate 方法确实是Matcher 的方法,那么您是对的。但事实并非如此!这是Pattern的一个方法,是线程安全的。
  • @Seelenvirtuose 从概念上讲你是对的:谓词不应该有状态,甚至不应该改变任何状态。但如果使用不当,可能会改变谓词主体使用的对象状态,从而破坏线程安全。 asPattern()当然不关心。
  • @davidxxx 你是对的。我在Pattern(与Matcher)的上下文中发表了我的评论,后来意识到OP确实搞砸了这两个类。我无法再编辑评论,所以我保持原样。

标签: java java-8 matcher


【解决方案1】:

Matcher 不是线程安全的,但 Pattern 是。
关于asPredicate(),您可以认为它是线程安全的,因为Pattern javadoc class 本身被定义为可供多个并发线程安全使用:

这个类的实例是不可变的,并且可以安全地被多个人使用 并发线程。 Matcher 类的实例不安全 这样的用途。

正如 Holger 所强调的,Pattern.asPredicate() 返回的 Predicate 没有被记录为线程安全的(也不是相反的),但它的实现证明它是:

public Predicate<String> asPredicate() {
    return s -> matcher(s).find();
}

Pattern.asPredicate() 只是在String 与类似于Pattern.matcher(CharSequence).find() 的模式之间进行匹配的另一种方法。

这个:

boolean isFound = pattern.matcher(myString).find(); 

可以这样实现:

boolean isFound = pattern.asPredicate().test(myString); 

所以这里的新功能是您可以在流中传递谓词或任何接受谓词的方法。这使得意图更加清晰:不需要操纵Pattern,而是操纵Predicate

Pattern pattern = ...;
...stream().filter(o-> pattern.matcher(o).find());

可以替换为:

Predicate<String> predicate = pattern.asPredicate();
List<String> strings = ...;
strings.stream().filter(predicate).(...); 
//or
strings.stream().filter(pattern.asPredicate()).(...);

【讨论】:

  • 您的示例pattern.matcher(myString).find() 表明实际操作必须经过Matcher。创建的Predicate 是每次创建一个新的Matcher(这将是线程安全的)还是创建一个并重用它(这不会),Java 8 中没有指定。谢天谢地,JDK 11 contains a clarification
  • @Holger 这确实没有直接指定,但 Pattern 类本身声明:“此类的实例是不可变的,并且可以安全地被多个并发线程使用。”多个并发线程安全使用”假设所有实例方法都是线程安全的,所以asPredicate() 是。关于JDK 11 javadoc,我想你指的是“好像它创建了一个匹配器”的部分。我发现“好像”的表述有点令人讨厌,因为模棱两可。
  • 是的,asPredicate() 的调用是每个类文档的线程安全的,matcher(…) 的调用也是如此。但这并没有说明返回的对象,正如matcher(…) 示例所示。返回的Predicate 是否是线程安全的,只能从它等同于s -&gt; matcher(s).find() 的声明中推导出来,但是如果你认为它太弱,你就不得不修改你的答案,因为Pattern 是线程安全并没有说明使用该模式的对象,例如 MatcherPredicate 实现。
  • @Holger 有趣,我只是从实现中扣除了这个;但这是否意味着Matcher::matcher 必须一直返回一个新实例?确实是这样,但是 return A new matcher for this pattern 是否足够?我想new这个词在这里是按字面意思理解的。
  • @Eugene 你的意思是Pattern::matcher,但是是的,“创建一个匹配器……”和“@Return 一个新的匹配器……”必须从字面上理解。其他一切都会破坏线程安全可重用性的目的。正如课堂文档所说,“......这么多匹配器可以共享相同的模式”。
【解决方案2】:

Matcher 没有asPredicate的方法;是Pattern。因此,返回的Predicate 也是线程安全的——它将以 new Matcher 的形式返回,Predicate 将从其构建——因为文档说它是不可变的。

【讨论】:

  • 没错,就是我编辑的时候出了点小错误。我修好了它。谢谢
猜你喜欢
  • 1970-01-01
  • 2012-08-21
  • 2013-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-08
  • 2019-09-22
相关资源
最近更新 更多