2016-08-25 3 views
1

У меня есть этот класс, который распространяется RecursiveAction. тот же класс содержит конструктор, который принимает массив как аргумент и метод compute(). Внутри метода вычисления, он говорит следующее: если array длина больше 500, разделите этот массив на две половины и отсортируйте их по методу MergeSort.merge(). если длина массива меньше 500, просто соберите array.Параллельное программирование. compute(), java

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); 
} 
} 
} 
} 

Это говорит «рекурсивно сортирует две половинки» и он делает это с помощью:

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

это означает, что каждый раз, когда newSortTask создается объект, compute() вызывается метод?

+0

Если список под THRESHOLD не создается, добавляется дополнительная SortTask. В противном случае создается по меньшей мере дополнительное число пар (2, 4, 6, 8 ...) SortTask. –

ответ

0

Ответ №. Вычисление не является частью конструктора Task. Самая простая ситуация - пул shutdownNow() - этот вызов будет пытаться прервать/прервать все отправленные задачи.

Каждый раз, когда 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 метод ваша полезная нагрузка задача - ForkJoinPool будет делать это на это график.

От ForkJoinTaskjavadoc:

Первичные механизмы координации вилы(), который организует асинхронное выполнение, а также присоединиться(), что не происходят, пока результат в выполнения задания не вычислен.

RecursiveTask реализует абстрактный метод:

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

ForkJoinWorkerThread имеет метод:

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

и на тех и doExec вызовов exec

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

хорошо, но как вы доберетесь туда? – Zgodni

+0

invokeAll вызывается в compute(), а вычисление() нигде не называется явно. так что еще раз, мне интересно, вызывается ли метод compute() каждый раз, когда создается объект SortTask, или это не так. – Zgodni

+0

Чтобы начать вычисление, вы должны вызвать 'new ForkJoinPool(). invoke (new SortTask (data));' –

0

Да, каждый раз, когда создается новый объект SortTask, вызывается метод compute(), потому что метод invokeAll вызывает набор задач в ForkJoinPool, который неявно вызывает вычисление для каждого из них.

Метод invoke() семантически эквивалентен fork(); join(), но всегда пытается начало Выполнение в текущей ветке.

Кроме того, из документации:

Как правило, конкретный ForkJoinTask подкласс (RecursiveAction/RecursiveTask) объявляет поля, содержащим его параметры, установленные в конструкторе, а затем определяет вычислительной метода в том, что каким-то образом использует методы управления, предоставляемые этим базовым классом.

Метод, используемый для сортировки их здесь на самом деле рекурсивно разделить их, что, когда они достигают ПОРОГ они будут сортироваться последовательно, метод слияния используется, чтобы объединить их после того, как они упорядочиваются. Посмотрите на этот аналогичный пример:

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; 
} 
} 

Когда coInvoke здесь FORKS обе задачи и возвращается, когда isDone выполняется для обоих.

+0

compute call is async –

+0

@SergeyRybalkin То, что я написал, было из документации !, я все еще верю в этот ответ, поэтому я не собираюсь его удалять. – TiMr

+0

amazing благодаря мужчине – Zgodni

Смежные вопросы