最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java并發(fā)學習之Executor源碼解析

 更新時間:2023年07月13日 11:20:01   作者:pq217  
這篇文章主要為大家介紹了java并發(fā)學習之Executor源碼示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

Runnable && Thread

Runnable和Thread都是java.lang包最基本的線程操作類,相當于官方的,而Executor接口及其實現(xiàn)都是Doug Lea寫的java.util.concurrent包下,屬于民間的,當然因為太牛逼了所以也在jdk中

先看官方提供的線程操作,其中Runnable是一個函數(shù)式接口

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

可以理解為一個待執(zhí)行的函數(shù),或者理解為一個任務(通過調用run方法可以實際的執(zhí)行任務)

Runable是一個定義的任務,而Thread是它的一個執(zhí)行者,它提供start方法可以開啟一個新線程執(zhí)行傳入的Runable任務,這很像命令模式,用戶通過實現(xiàn)Runable制定一個命令,交給Thread這個執(zhí)行者去具體執(zhí)行

Runnable && Thread

所以一般開啟新線程執(zhí)行方法的方式如下

Runnable task = () -> {
    // do something
};
new Thread(task).start(); // 開啟新線程執(zhí)行

而開啟新線程執(zhí)行方法也只有這一個途徑可走,就是必須通過官方的Thread.start方法

Executor

雖然開啟線程執(zhí)行任務只能走Thread.start方法,方法只有一個,但我們能做的是可以改變任務運行的方式,比如我們可以決定什么時候執(zhí)行任務,多少個任務共用某個線程排隊工作

最具代表性的就是線程池,線程池只是修改了任務執(zhí)行的方式:即所有任務共用固定數(shù)量的線程,但最終的運行終歸還是通過Thread.start方法實際在線程中執(zhí)行Runnable方法

Doug Lea所寫的java.util.concurrent.Executor把各種方式的Runnable執(zhí)行器的一個抽象

public interface Executor {
    void execute(Runnable command);
}

Executor

而且提供了一些常用的執(zhí)行器供我們使用,比如ThreadPoolExecutor(線程池),F(xiàn)orkJoinPool,當然我們也可以自己定義一個Executor按照自己的方式執(zhí)行任務,比如netty中實現(xiàn)的SingleThreadEventExecutor是一種單個線程依次處理所有任務的執(zhí)行器

ExecutorService

如果說Executor是一種對按自己套路執(zhí)行任務的執(zhí)行器,是一種抽象分類,那么ExecutorService就是其下的一個子分類,它是一種特殊的執(zhí)行器,從名字直譯來看:"執(zhí)行器服務",從一個執(zhí)行器升級為執(zhí)行服務,像不像某公司從賣產品業(yè)務升級為產品安裝售后整套服務

所以ExecutorService作為一個特殊的服務類Executor,不光能按照自己的方式執(zhí)行任務,還推出了一系列附加"服務",那就看看這種特殊的執(zhí)行器都提供了什么服務

public interface ExecutorService extends Executor {
    void shutdown();
    Future<?> submit(Runnable task);
    <T> Future<T> submit(Callable<T> task);
    ......
}

只貼了些重要方法,首先繼承了Executor肯定是要繼承void execute(Runnable) 方法代表它首先是一個任務執(zhí)行器

shutdown方法代表這個執(zhí)行器是有狀態(tài)的,可以關閉服務的

然后就是重量級的submit方法,這也是ExecutorService提供的最具特色的服務,如果打開ExecutorService的類,注釋第一句就寫著:

/**
 * An {@link Executor} that provides methods to manage termination and
 * methods that can produce a {@link Future} for tracking progress of
 * one or more asynchronous tasks.

翻譯過來大致就是ExecutorService是一個特殊的Executor執(zhí)行器,他可以終止服務并且可以創(chuàng)建一個Future來跟蹤任務執(zhí)行進度

ExecutorService的submit不光能接受Runnable,還可以接受一種新型任務形式:Callable,即有返回結果和異常的任務

Callable

上面我們總結Runnable是一種可執(zhí)行任務,而這種任務是沒有返回結果的,也不能拋出異常,很顯然現(xiàn)實中很多任務是需要有返回結果的,比如計算1+1等于幾的任務,所以為了擴展任務類型,Doug Lea又定義一種新的任務:Callable,而ExecutorService可以接受并處理這樣的任務

@FunctionalInterface
public interface Callable<V> {
    V call() throws Exception;
}

Future

submit執(zhí)行的返回值是一個Future,從注釋看出他可以跟蹤任務的進度,它就好比任務的一個訂單,通過訂單可以取消任務,查看任務進度等

  • boolean cancel(boolean) 取消
    取消任務,就好比在某寶買了個東西,本質就是提交一個"把東西給我送過來"的任務,而通過訂單我們就可以取消這個任務
  • isCancelled() && isDone()
    查看任務狀態(tài),是否取消和是否完成
  • V get()
    獲取任務執(zhí)行結果,如果沒完成則阻塞,如果是Runnable,返回的就是null

ExecutorService

AbstractExecutorService

ExecutorService制訂了一種新型執(zhí)行器,它的特殊在于可以跟蹤任務進度甚至取消任務,那么如何實現(xiàn)吶

首先execute方法只會單純的執(zhí)行任務,按照自己執(zhí)行器的邏輯調用Thread.start方法,不會有返回值,也不支持跟蹤進度或取消

所以解決方案只有一個:調包任務,具體這樣操作:當用戶提交任務,不是直接去execute執(zhí)行,而是把任務包裝為一個新任務,新任務執(zhí)行原任務的同時,還負責獲取任務結果,跟蹤任務狀態(tài)等工作,相當于是原任務的一個代理

以上即是AbstractExecutorService負責的工作,它是ExecutorService關于任務跟蹤業(yè)務的相關實現(xiàn)(解決方案即是代理任務),繼承了AbstractExecutorService的任務執(zhí)行器既可以實現(xiàn)跟蹤任務的功能

AbstractExecutorService

來看一下AbstractExecutorService的submit方法

public Future<?> submit(Runnable task) {
    if (task == null) throw new NullPointerException();
    // 生成一個依賴于原任務的新任務
    RunnableFuture<Void> ftask = newTaskFor(task, null);
    // 執(zhí)行新任務
    execute(ftask);
    // 返回新任務(充當任務跟蹤器)
    return ftask;
}

其中newTaskFor方法負責生成新任務,同時也是原任務的跟蹤器(訂單)

protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
    return new FutureTask<T>(runnable, value);
}

所以整個執(zhí)行過程就是把Runnable或Callable轉換為FutureTask的過程,而FutureTask首先是一個新任務(繼承Runnable),又是原任務的跟蹤器(繼承Future),這種任務歸類為RunnableFuture

public interface RunnableFuture<V> extends Runnable, Future<V> {
    void run();
}

FutureTask

接下來就看FutureTask是如何實現(xiàn)跟蹤替換原任務的,首先它的重點屬性如下

  • int state; 存儲原任務的執(zhí)行狀態(tài)
  • Callable<V> callable; 原任務Runnable也可以適配為返回null的Callable
  • Object outcome; 原任務的返回結果

再看一下重點方法

1.初始化,存儲原任務,任務狀態(tài)為NEW

public FutureTask(Callable<V> callable) {
    if (callable == null)
        throw new NullPointerException();
    this.callable = callable;
    this.state = NEW;       // ensure visibility of callable
}

2.run(),真實的被執(zhí)行任務,加入狀態(tài)判斷,執(zhí)行原任務通過try-catch獲取異常,通過outcome保存結果

public void run() {
    // 如果任務不是新狀態(tài),直接返回
    if (state != NEW ||
        !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                     null, Thread.currentThread()))
        return;
    try {
        // 獲取原任務
        Callable<V> c = callable;
        if (c != null && state == NEW) {
            V result;
            boolean ran;
            try {
                // 執(zhí)行原任務
                result = c.call();
                ran = true;
            } catch (Throwable ex) {
                result = null;
                ran = false;
                // 有異常設置異常
                setException(ex);
            }
            if (ran)
                // 設置outcome存儲返回值
                set(result);
        }
    } finally {
        // runner must be non-null until state is settled to
        // prevent concurrent calls to run()
        runner = null;
        // state must be re-read after nulling runner to prevent
        // leaked interrupts
        int s = state;
        if (s >= INTERRUPTING)
            handlePossibleCancellationInterrupt(s);
    }
}

3.get(),獲取結果,如果狀態(tài)未完成阻塞等待,完成則返回outcome

public V get() throws InterruptedException, ExecutionException {
    int s = state;
    // 如果任務未完成,阻塞等待
    if (s <= COMPLETING)
        s = awaitDone(false, 0L);
    // 任務完成,返回結果    
    return report(s);
}
private V report(int s) throws ExecutionException {
    Object x = outcome;
    if (s == NORMAL)
        return (V)x; // 返回結果即outcome
    if (s >= CANCELLED)
        throw new CancellationException();
    throw new ExecutionException((Throwable)x);
}

4.cancel(),只要把狀態(tài)設置為CANCEL,run時就會直接return而不會執(zhí)行原任務

public boolean cancel(boolean mayInterruptIfRunning) {
    // 狀態(tài)變?yōu)镃ANCELLED
    if (!(state == NEW &&
          UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
              mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
        return false;
    // 如果正在運行調用interrupt阻斷正在執(zhí)行的任務
    try {    // in case call to interrupt throws exception
        if (mayInterruptIfRunning) {
            try {
                Thread t = runner;
                if (t != null)
                    t.interrupt();
            } finally { // final state
                UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
            }
        }
    } finally {
        finishCompletion();
    }
    return true;
}

總結

AbstractExecutorService只是實現(xiàn)了讓任務變得可跟蹤,通過調包任務,而具體任務的執(zhí)行最終依然會調用execute,這個方法AbstractExecutorService并沒有實現(xiàn),因為這也是所有執(zhí)行器的差異所在,即按自己的方式選擇線程執(zhí)行任務, 比如ThreadPoolExecutor線程池的固定線程數(shù)執(zhí)行所有任務的模式,也就是只需要實現(xiàn)execute方法,而submit則交給父類AbstractExecutorService處理

以上就是java并發(fā)學習之Executor源碼解析的詳細內容,更多關于java并發(fā)Executor的資料請關注腳本之家其它相關文章!

相關文章

  • Java中Array、List、ArrayList的區(qū)別及說明

    Java中Array、List、ArrayList的區(qū)別及說明

    這篇文章主要介紹了Java中Array、List、ArrayList的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • JAVA中excel導出一對多合并具體實現(xiàn)

    JAVA中excel導出一對多合并具體實現(xiàn)

    項目中經常會使用到導出功能,有導出Word,有導出Excel的,下面這篇文章主要給大家介紹了關于JAVA中excel導出一對多合并具體實現(xiàn)的相關資料,需要的朋友可以參考下
    2023-09-09
  • Java transient 關鍵字詳解及實例代碼

    Java transient 關鍵字詳解及實例代碼

    本文章向大家介紹Java transient關鍵字的使用方法和實例,包括的知識點有transient的作用、transient使用小結、transient使用細節(jié),需要的朋友可以參考一下
    2016-12-12
  • springboot如何配置多kafka

    springboot如何配置多kafka

    這篇文章主要介紹了springboot如何配置多kafka問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • SpringBoot對Jar包進行加密的示例代碼

    SpringBoot對Jar包進行加密的示例代碼

    在當今互聯(lián)網(wǎng)高速發(fā)展的時代,軟件安全問題變得尤為突出,隨著開源技術的普及,Spring Boot等框架的應用越來越廣泛,但也伴隨著代碼被反編譯的風險,本文將探討在Spring Boot項目中對Jar包進行加密,以防止反編譯的安全實踐,需要的朋友可以參考下
    2023-12-12
  • SpringCloud @RefreshScope刷新機制深入探究

    SpringCloud @RefreshScope刷新機制深入探究

    RefeshScope這個注解想必大家都用過,在微服務配置中心的場景下經常出現(xiàn),他可以用來刷新Bean中的屬性配置,那大家對他的實現(xiàn)原理了解嗎?它為什么可以做到動態(tài)刷新呢
    2023-03-03
  • Java實現(xiàn)通過時間獲取8位驗證碼

    Java實現(xiàn)通過時間獲取8位驗證碼

    這篇文章主要為大家詳細介紹了Java如何通過時間獲取8位驗證碼(每兩個小時生成一個),文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-11-11
  • Java中volatile關鍵字的作用

    Java中volatile關鍵字的作用

    這篇文章主要介紹了Java中volatile關鍵字的作用,文章基于Java的相關資料展開對volatile關鍵字作用的詳細介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-04-04
  • Java教程之引用類型數(shù)組和繼承的意義詳解

    Java教程之引用類型數(shù)組和繼承的意義詳解

    這篇文章主要介紹了Java教程之引用類型數(shù)組和繼承的意義詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-06-06
  • Java 文件傳輸助手的實現(xiàn)(單機版)

    Java 文件傳輸助手的實現(xiàn)(單機版)

    這篇文章主要介紹了Java 文件傳輸助手的實現(xiàn)(單機版),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-05-05

最新評論

营口市| 江油市| 广西| 驻马店市| 中西区| 望奎县| 鄂托克前旗| 沅陵县| 琼海市| 大渡口区| 都江堰市| 施秉县| 定安县| 静安区| 大兴区| 澎湖县| 沙湾县| 许昌县| 太仆寺旗| 报价| 宝兴县| 清远市| 开鲁县| 惠水县| 衢州市| 天峻县| 三门县| 寻甸| 始兴县| 翼城县| 通山县| 油尖旺区| 滨州市| 文昌市| 玛多县| 柳林县| 余江县| 孝昌县| 海晏县| 资溪县| 渝中区|