当前位置: 首页 > 知识库问答 >
问题:

一个线程能阻塞完整的ForkJoinPool吗

洪弘壮
2023-03-14

我在读https://dzone.com/articles/think-twice-using-java-8

共有1个答案

牧熙云
2023-03-14

流操作不会阻塞池中的线程,而是会利用它们。根据工作负载的划分,可能所有线程都忙于处理首先开始的流操作,因此它们无法为另一个流操作提取工作负载。文章似乎错误地将“块”一词用于此场景。

值得注意的是,流API和默认实现是为不等待外部事件(阻塞线程)的CPU绑定任务设计的。如果以这种方式使用它,对于总体吞吐量来说,哪个任务让线程保持忙碌并不重要。但是,如果您同时处理不同的请求,并且希望在工作线程分配中有某种公平性,那么这就行不通了。

如果您继续阅读这篇文章,您会看到他们创建了一个示例,假设错误地使用了Stream API,使用了真正的阻塞操作,甚至将第一个示例调用为broked,尽管他们不必要地将其放在引号中。在这种情况下,错误不是使用并行流,而是将其用于阻塞操作。

long t0 = System.nanoTime();
new Thread(() -> {
    Stream.generate(() -> {
        long missing = TimeUnit.SECONDS.toNanos(3) + t0 - System.nanoTime();
        if(missing > 0) {
            System.out.println("blocking "+Thread.currentThread().getName());
            LockSupport.parkNanos(missing);
        }
        return "result";
    }).parallel().limit(100).forEach(result -> {});
    System.out.println("first (blocking) operation finished");
}).start();
for(int i = 0; i< 4; i++) {
    new Thread(() -> {
        LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
        System.out.println(Thread.currentThread().getName()
                          +" starting another parallel Stream");
        Object[] threads =
            Stream.generate(() -> Thread.currentThread().getName())
                .parallel().limit(100).distinct().toArray();
        System.out.println("finished using "+Arrays.toString(threads));
    }).start();
}
blocking ForkJoinPool.commonPool-worker-5
blocking ForkJoinPool.commonPool-worker-13
blocking Thread-0
blocking ForkJoinPool.commonPool-worker-7
blocking ForkJoinPool.commonPool-worker-15
blocking ForkJoinPool.commonPool-worker-11
blocking ForkJoinPool.commonPool-worker-9
blocking ForkJoinPool.commonPool-worker-3
Thread-2 starting another parallel Stream
Thread-4 starting another parallel Stream
Thread-1 starting another parallel Stream
Thread-3 starting another parallel Stream
finished using [Thread-4]
finished using [Thread-2]
finished using [Thread-3]
finished using [Thread-1]
first (blocking) operation finished

(详细信息可能不同)

然而,在创建发起线程(例如,那些接受外部请求的线程)的线程管理和公共池之间可能会发生冲突。但是,如前所述,如果您希望多个独立操作之间的公平性,并行流操作不是正确的工具。

 类似资料:
  • 我不明白以下几点: 用户级线程需要非阻塞系统调用,即多线程内核。否则,整个进程将在内核中阻塞,即使进程中还有可运行的线程。 内核线程如何处理阻塞系统调用?在用户级线程中,当一个线程进行阻塞系统调用(例如读取)时,为什么其他线程不能继续工作?

  • 我有4-5个工作线程处理大型消息队列。我还有另一段代码,它使用2-3个worker运行。我想在处理大型消息队列时阻止所有其他工作者。 我正在使用JDK6和Jms 编辑: 队列进程工作者从未终止。当没有消息时,它们阻塞队列。这些工作者由执行器线程池管理,如果我使用读写锁,其中一个工作者也会被阻塞。此外,如果使用循环屏障,那么我必须终止线程,以便重新传递阻塞的第二个进程。由于工作者是由线程池管理的,所

  • 我编写了一个简单的类,我计划将其扩展为客户端套接字编程应用程序的一部分。类涉及一个BlockingQueue(我从这里复制了代码:相当于Java的BlockingQueue的C++)。当我创建了下面的包装类的一个实例后,我打算让它生成一个单独的线程,该线程只需执行BlockingQueue上阻塞的printer()函数,直到有一个或多个字符串可用,然后它只需将字符串打印到控制台窗口。在我的预期应用

  • 背景我使用log4j2(2.12.1)与同步根和异步记录器。Lmax环形缓冲区大小默认为256*1024。我在控制台的appender。我用JSON布局记录MapMessage。我的日志消息的平均大小约为100字节。 有了上面的细节,我注意到很少有线程被阻塞在 我的问题是。。 环形缓冲区是否很快就满了,这导致主线程背压(在我的例子中,servlet容器线程是http-nio-8080-exec-1

  • 我试图用一个自定义对象创建一个新线程,然后从主线程调用这个自定义对象方法。其思想是,主线程可以继续执行其他任务,而自定义对象可以继续在第二个线程中工作: 输出为: 它应该更像这样: 所以主线程被阻塞,直到方法完成。主线程是否在第二个线程中等待完成(作为返回类型为空,我认为情况不会如此)?还是在第一个线程中执行,因此阻塞了它? 我知道使用下面的代码,我可以在另一个线程中执行,但它每次都会从头开始创建

  • 本文向大家介绍Jquery ajax 同步阻塞引起的UI线程阻塞问题,包括了Jquery ajax 同步阻塞引起的UI线程阻塞问题的使用技巧和注意事项,需要的朋友参考一下 最近做一个项目,遇到了一个问题同步ajax引起的ui线程阻塞问题,下面把我的问题解决过程分享给大家。 事情起因是这样的,因为页面上有多个相似的异步请求动作,本着提高代码可重用性的原则,我封装了一个名为getData的函数,它接收