【问题标题】:Is it discouraged to use Java 8 parallel streams inside a Java EE container?是否不鼓励在 Java EE 容器中使用 Java 8 并行流?
【发布时间】:2014-05-15 18:11:13
【问题描述】:

鉴于spawning threads in Java EE containers are discouraged。是否不鼓励在 Java EE 中使用Java 8 parallel streams,它可能会产生线程?

【问题讨论】:

  • @RobertHarvey 在 JavaEE 中使用线程是令人沮丧的——Java 8 引入了并行流(在后台使用线程)。我们可以在 JavaEE 中使用并行流还是不鼓励这样做?我认为这是一个公平而有趣的问题。我已经改写了一点 - 它可能会进一步改进。
  • @罗伯特哈维?不鼓励使用线程(甚至某些规范禁止使用线程),因为线程是由应用程序服务器本身管理的(参见右侧的第一个链接)——使用并行流可能会“破坏”——或者不会。这就是问题所在。根据规格,它可能会或可能不会“破坏东西”:这不是一种意见。只是我的 2 cts。您的电话 - 我今天休息! ;-)(做出决定后可以随意删除噪音)
  • 是的,它会破坏东西。例如,安全和事务上下文由 ThreadLocal 变量处理。而且 JPA 实体不是线程安全的。因此,无论您以何种方式生成线程,都会破坏安全性和事务处理。如果您想在 Java EE 环境中的线程中执行任务,Java EE 7 规范引入了应该使用的特殊执行器。但是 Java EE 落后于 Java SE,还没有为并行流做好准备。
  • 这是一个很好的问题,Java EE 工程师已经回答了。它们恢复为所有并行操作的顺序处理。您可以在 lambda-dev@openjdk.java.net 邮件列表中找到讨论。

标签: java jakarta-ee ejb java-8 java-stream


【解决方案1】:

编辑查看andrepnh 的替代答案。以下可能是计划,但在实践中似乎并没有这样发展。


我从 cmets 中提到的 lambda-dev mailing list discussion 中读取它的方式:生成线程的方式并不气馁 - 但在 Java EE 上下文中不会为您做任何事情。

来自链接的讨论:

Java EE 并发人员已经讨论过 这个,目前的结果是 FJP 将优雅地降级为 从内部运行时的单线程(甚至调用者上下文)执行 EE 容器

因此,您可以在同时在两种上下文中运行的过程或库中安全地使用并行流。当它在 SE 环境中运行时,它会使用神奇的并行恶作剧——但当它在 EE 环境中运行时,它会优雅地降级为串行执行。

注意:上面引用的短语是将来时 - 是否有人引用了某些权威文档?

【讨论】:

  • 将并行流处理优雅地降级为单线程还不是 Java EE 并发的一部分。所以在 Java EE 8 中使用并行流仍然是不安全的。未来计划在 Jakarta EE Con​​currency 中解决这个问题:github.com/eclipse-ee4j/concurrency-api/issues/46
【解决方案2】:

请注意,优雅降级到单线程是不可用的。我还认为这是因为 Shorn 的回答和邮件列表讨论,但我发现不是在研究 this question 时。该机制不在 Java EE 7 规范中,也不在 glassfish 4.1 中。即使另一个容器这样做,它也不是便携式的。

您可以通过调用以下方法进行测试:

@Singleton
public class SomeSingleton {
    public void fireStream() {
        IntStream.range(0, 32)
            .parallel()
            .mapToObj(i -> String.format("Task %d on thread %s", 
                i, Thread.currentThread().getName()))
            .forEach(System.out::println);
    }
}

你会得到类似的东西:

Info:   Task 20 on thread http-listener-1(4)
Info:   Task 10 on thread ForkJoinPool.commonPool-worker-3
Info:   Task 28 on thread ForkJoinPool.commonPool-worker-0
...

我还检查了 glassfish 4.1.1 的源代码,没有单独使用 ForkJoinPoolForkJoinWorkerThreadFactoryForkJoinWorkerThread

该机制可以添加到 EE 8,因为许多框架将利用 jdk8 功能,但我不知道它是否是规范的一部分。

【讨论】:

  • 无法通过将java.util.concurrent.ForkJoinPool.common.parallelism 系统属性设置为1 以可移植的方式实现优雅降级?
猜你喜欢
  • 1970-01-01
  • 2015-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-05
相关资源
最近更新 更多