简体   繁体   English

并行编程。 compute()方法,java

[英]Parallel programming. compute() method, java

I have this class which extends RecursiveAction . 我有这个扩展RecursiveAction类。 that same class contains constructor which takes array as argument and compute() method. 同一个类包含构造函数,它将数组作为参数和compute()方法。 Inside compute method, it says next: if array length is bigger than 500, split that array in two halves and sort them by MergeSort.merge() method. 在内部计算方法中,它接下来说:如果array长度大于500,则将该数组分成两半并按MergeSort.merge()方法对它们进行排序。 if array length is less than 500, just sort the array . 如果数组长度小于500,只需对array排序。

private static class SortTask extends RecursiveAction {
   private final int THRESHOLD = 500;
     private int[] list;
      SortTask(int[] list) {
       this.list = list;
         }
        @Override
protected void compute() {
if (list.length < THRESHOLD)
java.util.Arrays.sort(list);
else {
    // Obtain the first half
int[] firstHalf = new int[list.length / 2];
System.arraycopy(list, 0, firstHalf, 0, list.length / 2);


// Obtain the second half
int secondHalfLength = list.length - list.length / 2;
int[] secondHalf = new int[secondHalfLength];
System.arraycopy(list, list.length / 2,
secondHalf, 0, secondHalfLength);
// Recursively sort the two halves
invokeAll(new SortTask(firstHalf),
new SortTask(secondHalf));
// Merge firstHalf with secondHalf into list
MergeSort.merge(firstHalf, secondHalf, list);
}
}
}
}

It says "recursively sort the two halves" and it does that by: 它说“递归排序两半”,它通过以下方式实现:

invokeAll(new SortTask(firstHalf), new SortTask(secondHalf));

does that mean that every time new SortTask object is created, compute() method is called ? 这是否意味着每次创建new SortTask对象时,都会调用compute()方法?

The answer is No. Compute is not a part of Task constructor. 答案是否。计算不是Task构造函数的一部分。 The simpliest situation is pool shutdownNow() - this call will try to terminate/interrupt all submited tasks. 最简单的情况是pool shutdownNow() - 此调用将尝试终止/中断所有提交的任务。

Every time new SortTask created ForkJoinPool forks this task: 每次new SortTask创建ForkJoinPool此任务:

public static void invokeAll(ForkJoinTask<?>... tasks) {
    Throwable ex = null;
    int last = tasks.length - 1;
    for (int i = last; i >= 0; --i) {
        ForkJoinTask<?> t = tasks[i];
        if (t == null) {
            if (ex == null)
                ex = new NullPointerException();
        }
        else if (i != 0)
            t.fork();
    ...
}

compute method is your task payload - ForkJoinPool will do it on it's schedule . compute方法是你的任务负载 - ForkJoinPool将按照它的计划执行

From ForkJoinTask javadoc : 来自ForkJoinTask javadoc

The primary coordination mechanisms are fork(), that arranges asynchronous execution, and join(), that doesn't proceed until the task's result has been computed. 主要的协调机制是fork(),它安排异步执行,join(),在计算任务结果之前不会继续。

RecursiveTask implements abstract method: RecursiveTask实现抽象方法:

protected final boolean exec() {
    result = compute();
    return true;
}

ForkJoinWorkerThread has method: ForkJoinWorkerThread有方法:

final void More execTask(ForkJoinTask<?> t) {
    currentSteal = t;
    for (;;) {
       if (t != null)
           t.doExec();
    ...
}

and at the and doExec calls exec 并在和doExec调用exec

final void doExec() {
    if (status >= 0) {
        boolean completed;
        try {
            completed = exec();
    ...
}

Yes, every time new SortTask object is created, compute() method is called, because the method invokeAll forkes a set of tasks in a ForkJoinPool which implicitly calls compute for each one of them. 是的,每次创建新的SortTask对象时,都会调用compute()方法,因为方法invokeAll在ForkJoinPool中生成一组任务,它们隐式地为每个任务调用compute。

Method invoke() is semantically equivalent to fork(); 方法invoke()在语义上等同于fork(); join() but always attempts to begin execution in the current thread. join()但总是尝试在当前线程中开始执行。

Also from the documentation: 还来自文档:

Normally, a concrete ForkJoinTask subclass (RecursiveAction/RecursiveTask) declares fields comprising its parameters, established in a constructor, and then defines a compute method that somehow uses the control methods supplied by this base class. 通常,具体的ForkJoinTask子类(RecursiveAction / RecursiveTask)声明包含其参数的字段,在构造函数中建立,然后定义以某种方式使用此基类提供的控制方法的计算方法。

The method used to sort them here actually is to recursively divide them that when they reach the THRESHOLD they will be sorted sequentially, the merge method is used to merge them after they get sorted. 实际上用于对它们进行排序的方法实际上是递归地划分它们,当它们到达THRESHOLD时它们将按顺序排序,合并方法用于在它们被排序后合并它们。 Look at this similar example: 看看这个类似的例子:

class SortTask extends RecursiveAction {
final long[] array; final int lo; final int hi;
SortTask(long[] array, int lo, int hi) {
this.array = array; this.lo = lo; this.hi = hi;
}
protected void compute() {
 if (hi - lo < THRESHOLD)
   sequentiallySort(array, lo, hi);
  else {
   int mid = (lo + hi) >>> 1;
    coInvoke(new SortTask(array, lo, mid),
            new SortTask(array, mid+1, hi));
   merge(array, lo, hi);
       }
return null;
}
}

When coInvoke here Forks both tasks and returns when isDone holds for both. coInvoke在这里coInvoke两个任务时,当isDone为两个任务保持时返回。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM