java - 与 java8 文档中 CountedCompleter 的示例代码片段混淆

标签 java forkjoinpool

我读了关于 CountedCompleter 的 java8 文档,它给出了示例使用代码如下:

 class MyOperation<E> { void apply(E e) { ... }  }

 class ForEach<E> extends CountedCompleter<Void> {

   public static <E> void forEach(E[] array, MyOperation<E> op) {
     new ForEach<E>(null, array, op, 0, array.length).invoke();
   }

   final E[] array; final MyOperation<E> op; final int lo, hi;
   ForEach(CountedCompleter<?> p, E[] array, MyOperation<E> op, int lo, int hi) {
     super(p);
     this.array = array; this.op = op; this.lo = lo; this.hi = hi;
   }

   public void compute() { // version 1
     if (hi - lo >= 2) {
       int mid = (lo + hi) >>> 1;
       setPendingCount(2); // must set pending count before fork
       new ForEach(this, array, op, mid, hi).fork(); // right child
       new ForEach(this, array, op, lo, mid).fork(); // left child
     }
     else if (hi > lo)
       op.apply(array[lo]);
     tryComplete();
   }
 }

compute方法中,每个ForEach对象都会 fork 两个子任务并将待处理计数设置为2, 但是在compute方法的最后,tryComplete只能将待处理计数减一,如何 剩下的有吗??

最佳答案

看了ForkJoinPoolCountedCompleter的源码,终于明白了。

从根 CountedCompleter 派生的所有 CountedCompleters 将像树一样组织。当调用tryComplete时,如果当前pending计数为正,则会减1。否则会调用当前CountedCompleter的onCompletion,然后递归调用tryComplete 在父 CountedCompleter 上。如果父CountedCompleter为null,则表示它已经是根CountedCompleter,则整个任务完成。

所以我们知道:

  • CountedCompleter 任务在 compute() 方法完成后不会结束,它将等待直到待处理计数减少到 0
  • CountedCompleter 任务并不总是由根任务本身结束(与 RecursiveTaskRecursiveAction 非常不同),它可以由子任务结束' 尝试完成

然后让我们看看java 8 doc中的代码片段(注意序列号0:1:2:3:在代码中,这是一种可能的执行顺序):

 class MyOperation<E> { void apply(E e) { ... }  }

 class ForEach<E> extends CountedCompleter<Void> {

   public static <E> void forEach(E[] array, MyOperation<E> op) {
     new ForEach<E>(null, array, op, 0, array.length).invoke();
   }

   final E[] array; final MyOperation<E> op; final int lo, hi;
   ForEach(CountedCompleter<?> p, E[] array, MyOperation<E> op, int lo, int hi) {
     super(p);
     this.array = array; this.op = op; this.lo = lo; this.hi = hi;
   }

   public void compute() { // version 1
     if (hi - lo >= 2) {
       int mid = (lo + hi) >>> 1;
       setPendingCount(2); // 0: +2
       new ForEach(this, array, op, mid, hi).fork(); // 2: -1
       new ForEach(this, array, op, lo, mid).fork(); // 3: pending count == 0 complete
     }
     else if (hi > lo)
       op.apply(array[lo]);
     tryComplete();  // 1: -1
   }
 }

关于java - 与 java8 文档中 CountedCompleter 的示例代码片段混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60565580/

相关文章:

java - 使用 Lucene 4.3 进行分面搜索

java - ForkJoinPool 调度与 ExecutorService

java - 使用 java ForkJoinPool 调用 JdbcTemplate batchUpdate()

java - 如何更改字符串内的部分文本格式(颜色,sizebold斜体)?

进行双调排序时出现 java.lang.NoClassDefFoundError

java - ForkJoinPool 重置线程中断状态

java - waitQuise 超时后不返回

java - 如何在Java中实现搜索 token (如mac Lion中)?

java - getContentLength 在尝试获取 XML 文件时返回 -1

java - com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:通信链接失败