java Fork/Join 池、ExecutorService 和 CountDownLatch

标签 java multithreading executorservice countdownlatch forkjoinpool

我们在 java 中有三种不同的多线程技术 - Fork/Join pool, Executor Service & CountDownLatch

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

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

执行人服务 是一个扩展 Executor 类的接口(interface),表示异步执行。它为我们提供了管理异步任务结束和检测进度的机制。

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

倒计时锁 :( http://examples.javacodegeeks.com/core-java/util/concurrent/countdownlatch-concurrent/java-util-concurrent-countdownlatch-example/ )

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

我的假设:

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

这三种选择是互为补充还是互补 ?

最佳答案

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

ExecutorService

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

  • 无需等待即可启动并行独立任务
  • 等待完成所有任务

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

    它隐藏了 ThreadPoolExecutor 的低级细节.它不允许使用其他参数(Bounded Queue, Rejection Handler 等来微调性能),如 ThreadPoolExectuor .

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

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

    如果您需要以下功能,您可以提出自己的线程工厂
  • 设置更具描述性的线程名称
  • 设置线程守护进程状态
  • 设置线程优先级

  • 如果您的应用程序受到挂起的可运行/可调用任务数量的限制,您将通过设置最大容量来使用有界队列。一旦队列达到最大容量,您就可以定义 RejectionHandler。 Java 提供了四种拒绝处理程序policies .
  • 在默认 ThreadPoolExecutor.AbortPolicy ,处理程序在拒绝时抛出运行时 RejectedExecutionException。
  • ThreadPoolExecutor.CallerRunsPolicy ,调用execute的线程自己运行任务。这提供了一种简单的反馈控制机制,可以减慢提交新任务的速度。
  • ThreadPoolExecutor.DiscardPolicy ,无法执行的任务被简单地丢弃。
  • ThreadPoolExecutor.DiscardOldestPolicy ,如果执行器没有关闭,则丢弃工作队列头部的任务,然后重试执行(可能再次失败,导致重复。)

  • CountDownLatch
    CountDownLatch :这个框架允许一个java线程等待,直到其他线程集完成它们的任务。

    用例:
  • 实现最大并行:有时我们希望同时启动多个线程以实现最大并行
  • 在开始执行其他代码块之前等待 N 个线程完成
  • 死锁检测。

  • 更多详细信息列在此 article

    ForkJoinPool
    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 - 创建新线程的工厂。对于默认值,使用
    默认ForkJoinWorkerThreadFactory。

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

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

    关于主要查询:

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

    编辑:

    查看相关的 SE 问题:

    What are the advantages of using an ExecutorService?

    Java's Fork/Join vs ExecutorService - when to use which?

    关于java Fork/Join 池、ExecutorService 和 CountDownLatch,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31582548/

    相关文章:

    Java String 对象没有按时收集垃圾

    7000 个引用的 Java 源代码重构

    c++ - 在线程中运行函数

    java - 将 Await、Signal、SignalAll 替换为 wait、notify 和 notifyAll

    java - 在退出前恢复中断的不可取消任务

    java - 使用本地模拟器测试 PubsubIO 读取

    java - 在内部存储中创建公共(public)文件夹

    java - 在库中实现同步和异步方法的正确方法是什么?

    java - 使用来自 java 客户端的执行程序服务时,c 服务器未收到数据

    java - 多个用户同时访问的 Web 应用程序的 ExecutorService 线程池大小