多執行緒學習-day-06ForkJoin實現非同步方式遍歷指定資料夾檔案
阿新 • • 發佈:2018-11-26
執行緒基礎、執行緒之間的共享和協作
(目前會將一些概念簡單描述,一些重點的點會詳細描述)
學習目標:多執行緒的併發工具類(2)
利用ForkJoin來寫一個非同步方式遍歷指定資料夾下所有檔案(或指定檔案)程式
直接看程式碼吧,註釋也比較詳細了:
/** * 非同步遍歷指定盤的所有檔案 * * @author Administrator * */ public class FindDirFiles extends RecursiveAction { private static final long serialVersionUID = 7698200241798928022L; private File path; // 當前要搜尋的目錄 public FindDirFiles(File path) { this.path = path; } @Override protected void compute() { // 定義一個檔案目錄集合 List<FindDirFiles> subTasks = new ArrayList<>(); // 根據當前要搜尋目錄的,找到所有的檔案 File[] files = path.listFiles(); // 判斷是否為空,不為空則繼續往下搜尋 if (null != files) { // 不為空,則進行迴圈判斷 for (File file : files) { // 判斷是否是目錄 if (file.isDirectory()) { // 判斷是目錄,則儲存到一個檔案集合中 subTasks.add(new FindDirFiles(file)); } else { // 判斷不是目錄,則是檔案,則輸出檔名稱,這裡輸出所有的檔案,我這裡輸出太多,因此先輸出指定檔案 // System.out.println(file.getAbsolutePath()); // 如果遇到txt檔案,則輸出 if (file.getAbsolutePath().endsWith("xmind")) { System.out.println("檔案是:" + file.getAbsolutePath()); } } } // 判斷集合是否為空 if (null != subTasks && subTasks.size() > 0) { // 進行迴圈,把所有任務都invokeAll(), // 因為public <T> List<Future<T>> invokeAll(Collection<? extends // Callable<T>> tasks) // 可看出,invoke本身也是返回一個集合的結果 for (FindDirFiles subTask : invokeAll(subTasks)) { // 等待子任務完成 subTask.join(); } } } } public static void main(String[] args) { try { System.out.println("執行緒開始......."); // 定義ForkJoinPool物件池例項排程總任務 ForkJoinPool forkJoinPool = new ForkJoinPool(); // 初始化FindDirFiles物件 FindDirFiles findDirFiles = new FindDirFiles(new File("E:/")); // 非同步執行,如果是同步執行則用invoke forkJoinPool.execute(findDirFiles); // 證明是非同步執行 System.out.println("這裡我們要做一件從0加到100的求和"); // 休眠1秒 Thread.sleep(1000); // 迴圈計算0-100的求和運算 int sum = 0; for (int i = 0; i < 101; i++) { sum += i; } System.out.println("求和結果算出來了,sun = " + sum); // FindDirFiles物件要進行阻塞 findDirFiles.join(); System.out.println("執行緒結束......"); } catch (InterruptedException e) { e.printStackTrace(); } } } 控制檯輸出結果: 執行緒開始....... 這裡我們要做一件從0加到100的求和 檔案是:E:\辦公檔案\2014下半年檔案\2014年學校+辦公檔案\實習工作\2014-04-21\電子期刊軟體\資料標準專刊\歷史\專案專欄規劃.xmind 檔案是:E:\辦公檔案\2014下半年檔案\2014年學校+辦公檔案\實習工作\2014-04-28\電子期刊軟體\資料標準專刊\歷史\專案專欄規劃.xmind 求和結果算出來了,sun = 5050
在這裡我們可以看到,輸出的結果卻是是非同步的。
一、ForkJoinPool非同步和同步的區別:
1,呼叫execute()方法時,為非同步執行
2,呼叫invoke()方法時,為同步執行
二、invokeAll()方法
1,invokeAll()方法, 我們檢視原始碼的實現可以看出,返回一個集合形式的結果,因此可以在for迴圈的泛型裡面直接用invokeAll(集合物件)方法
2、呼叫了invokeAll()方法後,將所有迴圈內的子方法都join()起來,等待子任務的完成
因此用Fork/Join的場景有很多,可以留言一起探討。