当前位置: 首页 > 面试题库 >

java Fork / Join池,ExecutorService和CountDownLatch

文建业
2023-03-14
问题内容

我们在Java中使用了三种不同的多线程技术 -Fork / Join pool,Executor Service和CountDownLatch

叉子/加入池 (http://www.javacodegeeks.com/2011/02/java-forkjoin-parallel-
programming.html

Fork /
Join框架旨在使分治算法易于并行化。这种类型的算法非常适合可以分为两个或更多相同类型的子问题的问题。他们使用递归将问题分解为简单的任务,直到这些任务变得足够简单以至于可以直接解决。然后将子问题的解决方案合并以给出原始问题的解决方案

ExecutorService 是扩展Executor类并表示异步执行的接口。它为我们提供了管理结束并检测异步任务进度的机制。

invokeAll()
:执行给定的任务,并在所有任务完成时返回保存其状态和结果的Future列表。Future.isDone()对于返回列表的每个元素为true。

CountDownLatch :( http://examples.javacodegeeks.com/core-
java/util/concurrent/countdownlatch-concurrent/java-util-concurrent-
countdownlatch-example/)

CountDownLatch在同步中用于允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。

我的假设:

在这两种选择中,只有在完成所有任务/线程后才能知道最终结果。

这三种选择是相互补充还是补充


问题答案:

在过去三个月对各种多线程框架进行研究之后,我找到了问题的答案。

执行器服务

它简单易用,控制范围有限。你可以用

  1. 在不等待的情况下启动并行独立任务
  2. 等待所有任务完成

Callable/Runnable任务数量很少且无边界队列中的任务堆积不会导致内存堆积并降低系统性能时,我更喜欢这种方法。

它隐藏了的低级详细信息ThreadPoolExecutor。不允许使用中的其他参数(Bounded Queue, Rejection Handler等来微调演奏)ThreadPoolExectuor

线程池执行器

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, 
TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory,
RejectedExecutionHandler handler)

它为您提供更多控制。除了设置最小和最大线程外,您还可以设置队列大小和make BlockingQueue有界。

如果需要以下功能,可以提出自己的线程工厂

  1. 设置更具描述性的线程名称
  2. 设置线程守护程序状态
  3. 设置线程优先级

如果您的应用程序受到未决Runnable /
Callable任务数量的限制,则将通过设置最大容量来使用有界队列。一旦队列达到最大容量,就可以定义RejectionHandler。Java提供了四种类型的拒绝处理程序策略。

  1. 默认情况下ThreadPoolExecutor.AbortPolicy,处理程序在拒绝时抛出运行时RejectedExecutionException。

  2. 在中ThreadPoolExecutor.CallerRunsPolicy调用执行自己的线程运行任务。这提供了一种简单的反馈控制机制,将降低新任务的提交速度。

  3. 在中ThreadPoolExecutor.DiscardPolicy,简单地删除了无法执行的任务。

  4. 在中ThreadPoolExecutor.DiscardOldestPolicy,如果未关闭执行程序,则将丢弃工作队列开头的任务,然后重试执行(这可能再次失败,从而导致重复执行此操作)。

CountDownLatch

CountDownLatch :此框架允许Java线程等待,直到其他线程集完成其任务。

用例:

  1. 实现 最大并行度 :有时我们想同时启动多个线程以实现最大并行度

  2. 等待N个线程完成, 然后再开始执行其他代码块

  3. 死锁检测。

本文列出了更多详细信息

货叉池

ForkJoinPool是类似于Java的ExecutorService但有一个区别。这ForkJoinPool使得任务很容易将其工作分解为较小的任务,然后再将这些任务提交给ForkJoinPool。当空闲的工作线程从繁忙的工作线程队列中窃取任务时,在ForkJoinPool中发生任务窃取。

public ForkJoinPool(int parallelism,
            ForkJoinPool.ForkJoinWorkerThreadFactory factory,
            Thread.UncaughtExceptionHandler handler,
            boolean asyncMode)
Creates a ForkJoinPool with the given parameters.

参数:

并行度 -并行度级别。对于默认值,请使用Runtime.availableProcessors()

factory- 用于创建新线程的工厂。对于默认值,请使用defaultForkJoinWorkerThreadFactory。

handler- 因不可恢复的错误而终止的内部工作线程的处理程序

asyncMode- 如果为true,则为从未加入的分叉任务建立本地先进先出调度模式。

关于主要查询:

您可以使用ExecutorService.invokeAll()CountDownLatch框架或ForkJoinPool。所有这些框架都是相互补充的,不同的粒度可以控制从高级到低级任务的执行。

编辑:



 类似资料:
  • 问题内容: 假设我有一个利用该框架的应用程序 当我在调试器中运行此应用程序时,将使用以下(默认)名称创建一个线程:。如你所见,这并不是非常有用,而且据我所知,该框架没有提供一种简便的方法来命名已创建的线程或线程池。 那么,如何为线程/线程池提供名称呢?例如,。 问题答案: 你可以提供一个到。工厂将负责创建线程,并将能够为其命名。 引用Javadoc: 创建新线程 使用创建新线程。如果没有另外指定,

  • 我有一个ExecutorService创建如下- 我有一个元素列表(list)和一个操作(称为a),我需要对列表中的每个元素应用该操作。列表可以包含1到1000之间的任意数量的元素。该操作的类型为Callable。在操作A内部,它调用其他2个服务B和C。B和C也作为异步操作运行,并提交到同一线程池。 我为每个人创建了一个异步任务来并行执行,如下所示: 现在我有了一个未来的列表,我在上面循环得到结果

  • 我刚刚读完这篇文章:Java-5 ThreadPoolExecutor与Java-7 ForkJoinPool相比有什么优势?并觉得答案不够直截了当。 您能用简单的语言和示例解释一下Java7的Fork-Join框架和旧的解决方案之间的权衡吗? 我还从javaworld.com上读了谷歌的第一篇文章“Java提示:何时使用ForkJoinPool vs ExecutorService”,但这篇文章

  • 我已经在我的应用程序中使用创建了线程池,以调用供应商Web服务,使用下面的代码。 我想知道我们是否需要关闭线程池之类的,基本上我不希望在正式生产环境中挂起线程。

  • java.util.concurrent.ExecutorService接口是Executor接口的子接口,并添加了管理生命周期的功能,包括单个任务和执行程序本身。 ExecutorService方法 Sr.No. 方法和描述 1 boolean awaitTermination(long timeout, TimeUnit unit) 阻止所有任务在关闭请求之后完成执行,或发生超时,或者当前线程

  • 我已经搜索了网上的各种文章和堆栈溢出问题,但我不能找到这个完美的答案。有许多问题与此相近,但略有不同。 我们知道Java8Streams API在内部使用Fork-Join池。 现在我的问题是如何使用Fork-Join池来划分流管道中的任务? 假设我们有以下内容: null