一、フォーク、参加
1.定義:
フォーク参加枠組み:演算結果は、いくつかの小さなタスク(もはや除去されない分割)に大きなタスク、スプリット(フォーク)、場合に必要な小さなタスクであり、その後、一方が纏める参加。
2 ,,フォーク-参加は分割統治を反映しています。分割統治とは何ですか?
N <しきい値は、直接対処する問題の大きさN、。N>閾値は、Nをサブ問題に分解されたときに元の問題の同じ形でお互いのサブ問題の独立小規模を、Kです。元の問題への大きな解決策を得るために、サブ問題のデ合併。
図3に示すように、撮影した接着作業(workStealing)
4、フォーク、参加戦闘
4.1、フォーク/参加結果の戻り値を示すながら、同期呼び出しである:統計整数配列は、すべての要素を含むと
/ * * *整数配列生成ツール * / パブリック クラスMakeArray { // 配列長 パブリック 静的最終int型 array_length = 4000 ; パブリック 静的 INT [] makeArray(){ // 新しい新しい乱数ジェネレータ、 ランダムRD = 新しい新しいランダム(); int型 [] =結果新しい新しい INT [array_length]を、 ため(int型 I = 0 ; Iはarray_lengthを<; Iは++ ){ // アレイを充填する乱数 その結果、[I] = rd.nextInt(ARRAY_LENGTH * 3 )。 } 戻り値の結果; } }
/ * * *算出フレームフォーク-結合用い * / パブリック クラスSumArray { プライベート 静的 クラスを RecursiveTask <整数>延びSumTask { プライベート最終静的 INT THRESHOLD = MakeArray.ARRAY_LENGTH / 10 ; プライベート INT [] SRCを; // 実用に配列 プライベート int型 fromIndexの; // 統計に添字始める プライベート int型 toIndexのを; // 添字最後に統計 公共 SumTaskは(int型 [] SRC、INTたfromIndex、int型をたtoIndex){ この .SRC = SRC。 この .fromIndex = fromIndexの。 この .toIndex = toIndexの。 } @Override 保護整数{()を計算 場合(たtoIndex - fromIndexの< 閾値){ int型のカウント= 0 ; 用(INT I =たfromIndex; iが<=たtoIndex; iは++ ){ 試みる{ のThread.sleepを(1 )。 } キャッチ(InterruptedExceptionあるE){ e.printStackTrace(); } COUNT = COUNT + SRC [I]; } 戻りCOUNT; } 他{ // たfromIndex ..... ....... toIndexのMID。アルゴリズムは、ここで私たち自身の定義です:しきい値よりも大きいが均等に2つの部分に分かれて int型 MID = /(fromIndexの+ toIndexの)2 ; SumTaskは左 = 新しい新SumTask(SRC、fromIndexの、MID)を、 SumTask右 = 新新SumTask(SRC、MID、toIndexの); invokeAll(左、右)に、 復帰left.join()+ right.join()。 } } } パブリック 静的 ボイドメイン(文字列[]引数){ ForkJoinPoolプール = 新しいForkJoinPool()。 INT [] SRC = MakeArray.makeArray()。 SumTask innerFind = 新しい SumTask(SRC、0、src.length- 1 )。 長いスタート= にSystem.currentTimeMillis(); pool.invoke(innerFind)。// 同步调用 システム。アウト .println(「タスクが実行されて....... 」); 。システムOUTの .println(" ザ・はCOUNT IS " + innerFind.join()+ " 時間を過ごす:" +(のSystem.currentTimeMillis() -スタート)+ " MS " ); } / * * *注: *についてはこの実際に簡単な加算演算、シングルスレッドの処理速度より速いです。 *使用forkjoin後、マルチスレッド処理を使用。なぜならスレッド(コンテキストスイッチ)を切り替える必要があるため、時間が得られることは、よりforkjoin処理費やしました。 *機会に注意を払う必要がありますのでforkjoin使用してください。 * Redisのデータ処理(文字列)が比較的単純であるためのRedisは、シングルプロセス、シングルスレッドモードが、処理能力の使用は、非常に強力であるが理由です。 *シングルスレッドのプロセスを使用してプロセス間での切り替えを避けます。 * / }
デモは値を返す必要はありませんしながら、4.2、フォーク/非同期呼び出しに参加:特定の種類のファイルを探して、(サブディレクトリを含む)指定されたディレクトリトラバース
/ * * *特定の種類のファイルを見つけるために、(サブディレクトリを含む)指定されたディレクトリをトラバース フォークの値を返す必要はありません/参加* * / パブリック クラスはRecursiveAction {拡張FindDirsFiles // 現在のタスクは、カタログ検索する必要がある プライベートファイルのパスを、 公共FindDirsFiles(パスファイル){ この .path = パス; } @Overrideは、 保護された 、ボイド(計算)は{ 一覧 <FindDirsFiles> =サブタスク新しい新しいのArrayList <> (); []ファイルファイル =のpath.listFilesを(); // ファイルのディレクトリを取得します IF(ファイル!= nullの){ のために(ファイルのファイル:ファイル){ 場合(file.isDirectory()){ // 各サブディレクトリについては、サブタスクが作成されます subTasks.add(新新; FindDirsFiles(ファイル)) } 他に{ // チェックし、ファイルが検出された 場合(。file.getAbsolutePath()endsWith(" TXT " )){ システム。OUT .println(" ファイル:" + file.getAbsolutePath()); } } } IF(!{subTasks.isEmpty()) について(FindDirsFilesサブタスク:invokeAll(サブタスクへ)){ // 上記invlkeAll():サブタスク送信するために使用 subTask.joinを(); // サブタスク待つ } } } } パブリック 静的 ボイドメイン(文字列[]引数){ 試み{ // 総タスクスケジューラインスタンスForkJoinPoolと ForkJoinPoolプール= 新しい新しいForkJoinPool(); FindDirsFilesタスク = 新しい新しい FindDirsFiles(新しい新しいファイル(" D:\\ yishang " )); pool.execute(タスク)。 。システムOUT .println(" タスクの実行は........ IS " ); // メインスレッドは、自分のことをやって 試してみる{ のThread.sleep(1。); } キャッチ(InterruptedExceptionあるE){ e.printStackTrace( ); } int型 otherWork = 0 ; のための(int型 I = 0 ;私は< 100 ; Iは++ ){ otherWork = otherWork + I; } システム。OUT.println(" メインスレッドがかなっ行わ.....、otherWork = " + otherWork)。 task.join(); // 阻塞方法、 システム。アウト .println(「タスクの終了」)。 } キャッチ(例外e){ e.printStackTrace(); } } }