2016-08-25 19 views
1

私はこのクラスを拡張してRecursiveActionとしています。 同じクラスには、配列を引数とするコンストラクタと、compute()メソッドが含まれています。 計算方法の中では、次のようになります。の長さが500より大きい場合は、その配列を2つの半分に分割し、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は作成されません。それ以外の場合は、少なくともSortTaskの追加のペア番号(2,4,6,8 ...)が作成されます。 –

答えて

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は抽象メソッドを実装しています

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()は明示的に呼び出されません。だからもう一度、私はcompute()がSortTaskオブジェクトが作成されるたびに呼び出されるのか、それとも真でないのか不思議です – Zgodni

+0

計算を開始するには 'new ForkJoinPool()。invoke(new SortTask(data));を呼び出してください。 –

0

はい、時:

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

ForkJoinWorkerThreadはメソッドを持っています新しいSortTaskオブジェクトが作成されるたびに、invokeAllメソッドはForkJoinPool内のタスクのセットを強制的に呼び出すため、compute()メソッドが呼び出されます。これは暗黙的にそれぞれのオブジェクトに対して計算を呼び出します。

メソッドinvoke()は意味的にfork()に相当します。 join()ではなく、常に現在のスレッドでbeginの実行を試みます。通常、コンクリートForkJoinTaskサブクラス(RecursiveAction/RecursiveTask)はコンストラクタに設立、そのパラメータを含むフィールドを宣言

、及びその計算メソッドを定義:

ドキュメントからまた

何とかこの基本クラスが提供するコントロールメソッドを使用します。

ここで実際にソートする方法は、THRESHOLDに達すると順番にソートされ、ソート後にマージメソッドがマージされるという再帰的な分割方法です。 isDoneが両方成立するとき

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ここフォークタスクとリターンの両方:この同様の例を見てください。

+0

計算コールはasync –

+0

@ SergeyRybalkinです。私が書いたのはドキュメンテーションです!私はまだこの答えを信じていますので、私はそれを削除しません。 – TiMr

+0

すばらしい 感謝マン – Zgodni

関連する問題