GPars(5):Fork-Join

Fork/join主要用於問題分解處理,分而治之。html

Fork/join算法將問題劃分紅多個小的子問題,對每一個子問題運用一樣的算法,當子問題足夠小時,問題就能夠直接獲得解決。全部子問題都解決了,結合起來父問題也就獲得瞭解決。node

JSR-166y類庫對Fork/join支持至關不錯,但有些問題若是不注意,還會遇到麻煩。並且還得本身處理threads、pools及synchronization barriers(同步障)。GPars隱藏了這些東西,讓你用起Fork/join來更加方便。下例是統計一指定目錄及其子目錄下文件個數的算法:算法

import groovyx.gpars.AbstractForkJoinWorker
import static groovyx.gpars.Parallelizer.*
public final class FileCounter extends AbstractForkJoinWorker

   
   
   
   

  
   
  { private final File file; def FileCounter(final File file) { this.file = file } protected void compute() { long count = 0; file.eachFile { if (it.isDirectory()) { println "Forking a thread for $it" //fork一個子任務 forkOffChild(new FileCounter(it)) } else { count++ } } //用子任務結果計算並保存本任務結果 setResult(count + ((childrenResults)?.sum() ?: 0)) } } doParallel(1) { pool -> //1個線程也能搞定 println """Number of files: ${orchestrate( new FileCounter( new File("...目錄名...") ) )}""" } 

  

上例中Parallelizer.orchestrate()方法根據傳遞進的AbstractForkJoinWorker類型的參數(根任務)建立一個ForkJoinOrchestrator並運行該AbstractForkJoinWorker,等待結果返回。childrenResults是AbstractForkJoinWorker的屬性,等待子任務結果返回,返回值爲List類型。安全

Fork/Join操做之因此能安全地由成若干小線程運行,要歸功於內部TaskBarrier類對線程的同步。當算法中一個線程被阻塞等待其子問題得以完成時,該線程會被歸還到池內,以用於任務隊列中其餘可運行子問題。儘管算法建立了許多任務(因爲子目錄不少),並且都要等其子目錄任務完成,但最少只需一個線程就足以保持運算進行。併發

GPars指南中還給出了一個比較複雜的Mergesort的例子,有興趣的讀者能夠參考。ide

本系列的其餘文章:ui

相關文章
相關標籤/搜索