欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Future cancel迷惑性boolean入?yún)⒔馕?/h1>
 更新時(shí)間:2023年02月28日 16:49:13   作者:Code皮皮蝦  
這篇文章主要為大家介紹了Future cancel迷惑性boolean入?yún)⒔馕?,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

當(dāng)我們使用線程池submit一個(gè)任務(wù)后,會(huì)返回一個(gè)Future,而在Future接口中存在一個(gè)cancel方法,來幫助我們?nèi)∠羧蝿?wù)。

但是cancel方法有一個(gè)boolean類型的入?yún)?,比較迷惑,之前也了解過該入?yún)?code>true 和 false的區(qū)別,但過一段時(shí)間之后就又忘了,遂寫了本文進(jìn)行記錄,順便了解下源碼~

/**
 * Attempts to cancel execution of this task.  This attempt will
 * fail if the task has already completed, has already been cancelled,
 * or could not be cancelled for some other reason. If successful,
 * and this task has not started when {@code cancel} is called,
 * this task should never run.  If the task has already started,
 * then the {@code mayInterruptIfRunning} parameter determines
 * whether the thread executing this task should be interrupted in
 * an attempt to stop the task.
 *
 * <p>After this method returns, subsequent calls to {@link #isDone} will
 * always return {@code true}.  Subsequent calls to {@link #isCancelled}
 * will always return {@code true} if this method returned {@code true}.
 *
 * @param mayInterruptIfRunning {@code true} if the thread executing this
 * task should be interrupted; otherwise, in-progress tasks are allowed
 * to complete
 * @return {@code false} if the task could not be cancelled,
 * typically because it has already completed normally;
 * {@code true} otherwise
 */
boolean cancel(boolean mayInterruptIfRunning);

上面是cancel方法的接口定義,當(dāng)然英文看著麻煩,咱直接翻譯成看得懂的~

cancel方法,會(huì)嘗試取消任務(wù)的執(zhí)行,但如果任務(wù)已經(jīng)完成、已經(jīng)取消或其他原因無法取消,則嘗試取消任務(wù)失敗。

如果取消成功,并且在取消時(shí)

  • 該任務(wù)還未執(zhí)行,那么這個(gè)任務(wù)永遠(yuǎn)不會(huì)執(zhí)行。
  • 如果該任務(wù)已經(jīng)啟動(dòng),那么會(huì)根據(jù)cancelboolean入?yún)頉Q定是否中斷執(zhí)行此任務(wù)的線程來停止任務(wù)。

通過注釋我們大致能了解到cancel的一個(gè)作用,但是還不夠細(xì)致,接下來我們通過源碼解讀詳細(xì)的帶大家了解一下~

FutureTask任務(wù)狀態(tài)認(rèn)知

首先,我們先了解下FutureTask中對(duì)任務(wù)狀態(tài)的定義

在使用線程池submit后,實(shí)際上是返回的一個(gè)FutureTask,而FutureTask中對(duì)于任務(wù)定義了以下狀態(tài),并且在注釋中,也定義了狀態(tài)的流轉(zhuǎn)過程~

/**
 * Possible state transitions:
 * NEW -> COMPLETING -> NORMAL
 * NEW -> COMPLETING -> EXCEPTIONAL
 * NEW -> CANCELLED
 * NEW -> INTERRUPTING -> INTERRUPTED
 */
private volatile int state;
private static final int NEW          = 0;
private static final int COMPLETING   = 1;
private static final int NORMAL       = 2;
private static final int EXCEPTIONAL  = 3;
private static final int CANCELLED    = 4;
private static final int INTERRUPTING = 5;
private static final int INTERRUPTED  = 6;

但是通過對(duì)上面狀態(tài)定義的了解,我們可以發(fā)現(xiàn),在FutureTask中并沒有一個(gè)表明任務(wù)處于執(zhí)行中的一個(gè)狀態(tài)!

直接看FutureTaskrun方法源碼

public void run() {
    if (state != NEW ||
        !RUNNER.compareAndSet(this, null, Thread.currentThread()))
        return;
    try {
        Callable<V> c = callable;
        if (c != null && state == NEW) {
            V result;
            boolean ran;
            try {
                // 執(zhí)行任務(wù)
                result = c.call();
                ran = true;
            } catch (Throwable ex) {
                result = null;
                ran = false;
                // 執(zhí)行異常
                setException(ex);
            }
            if (ran)
                // 正常執(zhí)行完畢
                set(result);
        }
    } finally {
      //... 省略
    }
}
?
protected void setException(Throwable t) {
  if (STATE.compareAndSet(this, NEW, COMPLETING)) {
    outcome = t;
    STATE.setRelease(this, EXCEPTIONAL); // final state
    finishCompletion();
  }
}
?
protected void set(V v) {
  if (STATE.compareAndSet(this, NEW, COMPLETING)) {
    outcome = v;
    STATE.setRelease(this, NORMAL); // final state
    finishCompletion();
  }
}

通過上面源碼,我們也能了解到

  • 當(dāng)任務(wù)正常執(zhí)行完畢時(shí),任務(wù)狀態(tài)流轉(zhuǎn): NEW -> COMPLETING -> NORMAL
  • 任務(wù)執(zhí)行異常時(shí),任務(wù)狀態(tài)流轉(zhuǎn): NEW -> COMPLETING -> EXCEPTIONAL

所以,當(dāng)任務(wù)剛創(chuàng)建,或者是任務(wù)在執(zhí)行過程中,任務(wù)的狀態(tài)都是NEW

cancel源碼分析

此時(shí)再來分析cancel源碼

public boolean cancel(boolean mayInterruptIfRunning) {
    // NEW為新建或者運(yùn)行態(tài)
    // 1. 此時(shí)任務(wù)已經(jīng)不是NEW,說明要么是完成要么是異常,取消不了,所以返回false
    // 2. 此時(shí)任務(wù)還是NEW,如果我們傳入true,則CAS標(biāo)記任務(wù)為INTERRUPTING,否則是CANCELLED
    // 防止并發(fā)取消任務(wù),CAS只會(huì)有一個(gè)線程成功,其余線程失敗
    if (!(state == NEW && STATE.compareAndSet
          (this, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
        return false;
    try {    
        // 傳入true,則打斷該任務(wù)的執(zhí)行線程
        if (mayInterruptIfRunning) {
            try {
                Thread t = runner;
                if (t != null)
                    t.interrupt();
            } finally {
                // 比較任務(wù)狀態(tài)為INTERRUPTED
                STATE.setRelease(this, INTERRUPTED);
            }
        }
    } finally {
        finishCompletion();
    }
    return true;
}

通過對(duì)FutureTask任務(wù)狀態(tài)的認(rèn)知,再結(jié)合對(duì)cancel源碼的分析

我們可以總結(jié)出以下結(jié)論

當(dāng)任務(wù)已經(jīng)完成或者異常時(shí),無法取消任務(wù)

任務(wù)處于新建或者運(yùn)行狀態(tài)時(shí)

cancel方法入?yún)魅?code>true

將任務(wù)狀態(tài)NEW -> INTERRUPTING -> INTERRUPTED,并打斷執(zhí)行該任務(wù)的線程

cancel方法入?yún)魅?code>false

將任務(wù)狀態(tài)NEW -> CANCELLED

但有個(gè)問題,傳入false只是將狀態(tài)從NEW變成CANCELLED嘛,這好像沒啥用啊?

當(dāng)然不是,此時(shí)我們需要再回頭看看FutureTaskrun方法

public void run() {
    if (state != NEW ||
        !RUNNER.compareAndSet(this, null, Thread.currentThread()))
        return;
    try {
        Callable<V> c = callable;
        if (c != null && state == NEW) {
            V result;
            boolean ran;
            try {
                result = c.call();
                ran = true;
            } catch (Throwable ex) {
                result = null;
                ran = false;
                // 執(zhí)行異常
                setException(ex);
            }
            if (ran)
                // 正常執(zhí)行完畢
                set(result);
        }
    } finally {
      //... 省略
    }
}

run方法開頭我們可以看到,如果任務(wù)的狀態(tài)不是NEW,那么會(huì)直接return,不執(zhí)行任務(wù)

那此時(shí)再想想傳入false將任務(wù)狀態(tài)從NEW -> CANCELLED,是不是當(dāng)任務(wù)還沒有開始執(zhí)行時(shí),我們cancel(false)就可以取消掉未執(zhí)行的任務(wù)了~

總結(jié)

通過上面的源碼解讀,我們大致能了解了cancel的機(jī)制,但是我們還是完善的總結(jié)一下

任務(wù)如果不是NEW狀態(tài)是不會(huì)執(zhí)行的

cancel取消任務(wù)會(huì)改變?nèi)蝿?wù)的狀態(tài)

  • 如果傳入true, 則將任務(wù)狀態(tài)NEW -> INTERRUPTING -> INTERRUPTED,并打斷執(zhí)行該任務(wù)的線程
  • 如果傳入false,將任務(wù)狀態(tài)NEW -> CANCELLED

傳入false只能取消還未執(zhí)行的任務(wù)

傳入true,能取消未執(zhí)行的任務(wù),能打斷正在執(zhí)行的任務(wù)

擴(kuò)展知識(shí)點(diǎn)

cancel源碼中,我們可以看到finally中會(huì)去調(diào)用finishCompletion

那么,finishCompletion是干啥的呢?

private void finishCompletion() {
    // assert state > COMPLETING;
    for (WaitNode q; (q = waiters) != null;) {
        // 原子性將WAITERS設(shè)置為null
        if (WAITERS.weakCompareAndSet(this, q, null)) {
          
            // 遍歷WAITERS,將阻塞的線程都喚醒
            for (;;) {
                Thread t = q.thread;
                if (t != null) {
                    q.thread = null;
                    LockSupport.unpark(t);
                }
                WaitNode next = q.next;
                if (next == null)
                    break;
                q.next = null;
                q = next;
            }
            break;
        }
    }
?
    // 擴(kuò)展方法,交給自己實(shí)現(xiàn)
    done();
?
    callable = null;
}

大家可以想想,當(dāng)我們submit一個(gè)任務(wù)時(shí),一般情況下都會(huì)需要去獲取他的返回值,會(huì)調(diào)用get方法進(jìn)行阻塞獲取

FutureTask中,會(huì)維護(hù)一條鏈表,該鏈表記錄了等待獲取該任務(wù)返回值被阻塞的線程

在調(diào)用get方法時(shí),會(huì)將組裝waiters鏈表

所以,當(dāng)我們?nèi)∠粋€(gè)任務(wù)時(shí),是不是也應(yīng)該去將阻塞等待獲取該任務(wù)的所有線程進(jìn)行喚醒,而finishCompletion方法就是做這個(gè)事情的~

以上就是Future cancel迷惑性boolean入?yún)⒔馕龅脑敿?xì)內(nèi)容,更多關(guān)于Future cancel boolean入?yún)⒌馁Y料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Spring Framework遠(yuǎn)程代碼執(zhí)行漏洞分析(最新漏洞)

    Spring Framework遠(yuǎn)程代碼執(zhí)行漏洞分析(最新漏洞)

    Spring Framework 是一個(gè)開源應(yīng)用框架,旨在降低應(yīng)用程序開發(fā)的復(fù)雜度,它具有分層體系結(jié)構(gòu),允許用戶選擇組件,同時(shí)還為 J2EE 應(yīng)用程序開發(fā)提供了一個(gè)有凝聚力的框架,對(duì)Spring遠(yuǎn)程代碼執(zhí)行漏洞相關(guān)知識(shí)感興趣的朋友一起看看吧
    2022-04-04
  • Java使用Arrays.sort()方法實(shí)現(xiàn)給對(duì)象排序

    Java使用Arrays.sort()方法實(shí)現(xiàn)給對(duì)象排序

    這篇文章主要介紹了Java使用Arrays.sort()方法實(shí)現(xiàn)給對(duì)象排序,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • 在IDEA中創(chuàng)建Web項(xiàng)目的詳細(xì)過程

    在IDEA中創(chuàng)建Web項(xiàng)目的詳細(xì)過程

    這篇文章主要給大家介紹了關(guān)于在IDEA中創(chuàng)建Web項(xiàng)目的詳細(xì)過程,很多朋友可能在學(xué)習(xí)java基礎(chǔ)的時(shí)候已經(jīng)熟練掌握了IDEA創(chuàng)建java項(xiàng)目的基本步驟,但隨著學(xué)習(xí)技術(shù)的不斷深入,不同的IDEA版本可能在項(xiàng)目的創(chuàng)建頁面上出現(xiàn)些許的出入,需要的朋友可以參考下
    2023-10-10
  • javaweb中ajax請(qǐng)求后臺(tái)servlet(實(shí)例)

    javaweb中ajax請(qǐng)求后臺(tái)servlet(實(shí)例)

    下面小編就為大家?guī)硪黄猨avaweb中ajax請(qǐng)求后臺(tái)servlet(實(shí)例)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-06-06
  • Java多線程Atomic包操作原子變量與原子類詳解

    Java多線程Atomic包操作原子變量與原子類詳解

    這篇文章主要介紹了Java多線程Atomic包操作原子變量與原子類詳解,簡(jiǎn)單介紹了Atomic,同時(shí)涉及java.util.concurrent中的原子變量,Atomic類的作用等相關(guān)內(nèi)容,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • JavaWeb 入門:Hello Servlet

    JavaWeb 入門:Hello Servlet

    這篇文章主要介紹了Servlet開發(fā)JavaWeb工程示例詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-07-07
  • java 中數(shù)組初始化實(shí)例詳解

    java 中數(shù)組初始化實(shí)例詳解

    這篇文章主要介紹了 本文主要講數(shù)組的初始化方法、可變參數(shù)列表以及可變參數(shù)列表對(duì)函數(shù)重載的影響的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • 使用Mybatis的Batch?Insert?Support?實(shí)現(xiàn)批量插入

    使用Mybatis的Batch?Insert?Support?實(shí)現(xiàn)批量插入

    這篇文章主要介紹了使用Mybatis的Batch?Insert?Support?實(shí)現(xiàn)批量插入。具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • SpringBoot + Shiro前后端分離權(quán)限

    SpringBoot + Shiro前后端分離權(quán)限

    這篇文章主要為大家詳細(xì)介紹了SpringBoot + Shiro前后端分離權(quán)限,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • Java泛型之上界下界通配符詳解

    Java泛型之上界下界通配符詳解

    這篇文章主要介紹了Java泛型之上界下界通配符詳解,學(xué)習(xí)使用泛型編程時(shí),更令人困惑的一個(gè)方面是確定何時(shí)使用上限有界通配符以及何時(shí)使用下限有界通配符。本文提供一些設(shè)計(jì)代碼時(shí)要遵循的一些準(zhǔn)則。,需要的朋友可以參考下
    2019-06-06

最新評(píng)論