第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

Executor 應(yīng)用示例

1. 前言

上一節(jié)我們學(xué)習(xí)了 Executor 的基本概念和核心 API,本節(jié)帶領(lǐng)大家實(shí)現(xiàn)一個(gè)具體的應(yīng)用案例。從實(shí)際應(yīng)用中感受一下 Executor 框架的使用,以及此框架帶來(lái)的便利。

本節(jié)先描述待實(shí)現(xiàn)的案例內(nèi)容,接著做編碼實(shí)現(xiàn),然后總結(jié)使用過(guò)程中的注意事項(xiàng)。

2. 案例描述

我們可以通過(guò)手工創(chuàng)建線程做邏輯單元的執(zhí)行,但是當(dāng)存在大量的需要執(zhí)行的邏輯單元也是這樣處理,就會(huì)出現(xiàn)很多麻煩的事情,且效率非常低下。手工創(chuàng)建線程并做線程管理,需要我們實(shí)現(xiàn)很多與業(yè)務(wù)無(wú)關(guān)的控制代碼,另外手工不停的創(chuàng)建線程并做線程銷毀,會(huì)浪費(fèi)很多系統(tǒng)資源。

我們?cè)趯?shí)際項(xiàng)目中,常常通過(guò)使用 java 提供好的非常好用的線程框架 Executor 進(jìn)行任務(wù)執(zhí)行操作。

有這樣一個(gè)場(chǎng)景:需要對(duì)某個(gè)目錄下的所有文件(成百上千)進(jìn)行加密并用文件的 MD5 串修改文件名稱。

在開始動(dòng)手實(shí)現(xiàn)之前,我們先做一個(gè)簡(jiǎn)單的分析。在這個(gè)案例中,我們將 “對(duì)文件進(jìn)行加密、生成 MD5 串、修改文件名稱” 作為待執(zhí)行任務(wù)的內(nèi)容。所有文件形成的列表就是我們待處理的數(shù)據(jù)范圍。為了校驗(yàn)整個(gè)處理過(guò)程是否有文件遺漏,我們最終需要核對(duì)處理結(jié)果。為了方便演示,下面編碼中部分?jǐn)?shù)據(jù)采用了模擬的方式生成。

3. 編碼實(shí)現(xiàn)

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ExecutorTest {

    // 模擬待處理的文件列表
    private static int fileListSize = new Random().nextInt(6);
    private static String[] fileList = new String[fileListSize];
    static {
        for(int i=0; i<fileListSize; i++) {
            fileList[i] = "fileName" + i;
        }
    }

    // 主線程
    public static void main(String[] args) throws Exception {
        // 創(chuàng)建用于處理任務(wù)的線程池
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        // 任務(wù)提交,每一個(gè)任務(wù)處理一個(gè)文件
        List<FileDealTask> tasks = new ArrayList<>();
        for(int i=0; i<fileListSize; i++) {
            tasks.add(new FileDealTask(0, fileListSize, fileList[i]));
        }
        // 等待異步處理結(jié)果返回
        List<Future<Integer>> results = executorService.invokeAll(tasks);
        // 獲取任務(wù)執(zhí)行結(jié)果
        Integer total = 0;
        for (Future<Integer> result : results) {
            total = total + result.get();
        }
        System.out.println("預(yù)備處理的文件個(gè)數(shù)" + fileListSize + ",總共處理的文件個(gè)數(shù):" + total);
        // 關(guān)閉線程池
        executorService.shutdown();
    }
}

上面代碼注釋已經(jīng)很清楚了,我們觀察下面的代碼,看看任務(wù)代碼。

import java.util.Random;
import java.util.concurrent.Callable;

public class FileDealTask implements Callable<Integer> {

    private String fileName;

    public FileDealTask(int first, int last, String fileName) {
        this.fileName = fileName;
    }

    @Override
    public Integer call() throws Exception {
        try {
            Thread.sleep(new Random().nextInt(2000));
            System.out.println(Thread.currentThread().getName() + ":文件" + fileName + "已處理完畢");
        } catch (Exception e) {
            return 0;
        }
        return 1;
    }
}

我們通過(guò)在 IDE 中運(yùn)行上面這個(gè)示例,看看實(shí)際的運(yùn)行結(jié)果。
【補(bǔ)充視頻】

上面代碼邏輯中有隨機(jī)內(nèi)容,每次運(yùn)行結(jié)果會(huì)有差異,運(yùn)行上面的代碼,我們觀察運(yùn)行結(jié)果:

pool-1-thread-2:文件fileName1已處理完畢
pool-1-thread-3:文件fileName2已處理完畢
pool-1-thread-1:文件fileName0已處理完畢
預(yù)備處理的文件個(gè)數(shù)3,總共處理的文件個(gè)數(shù):3

和我們的預(yù)期一致。

4. 注意事項(xiàng)

  1. Executors 是 Executor 框架體系中的一個(gè)獨(dú)立的工具類,用于快速創(chuàng)建各類線程池,在實(shí)際應(yīng)用中,如果需要對(duì)線程池的各類參數(shù)做更多的自定義,可以參考此類的實(shí)現(xiàn)。
  2. 做好評(píng)估權(quán)衡,當(dāng)需要處理的數(shù)據(jù)量不是特別大時(shí),沒(méi)有必要使用 Executor。其底層使用多線程的方式處理任務(wù),涉及到線程上下文的切換,當(dāng)數(shù)據(jù)量不大的時(shí)候使用串行會(huì)比使用多線程快。
  3. 在使用時(shí),如果主線程不關(guān)心子任務(wù)的執(zhí)行結(jié)果,請(qǐng)使用 Runnable 接口封裝任務(wù)的執(zhí)行邏輯。

5. 視頻演示

6. 小結(jié)

本節(jié)通過(guò)一個(gè)實(shí)際例子的編碼實(shí)現(xiàn),展示了 Executor 的具體用法。當(dāng)然本節(jié)中的用法相對(duì)比較簡(jiǎn)單,更多的用法還需要大家進(jìn)一步學(xué)習(xí),希望大家多思考勤練習(xí),早日掌握之。