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

詳解FutureTask如何實(shí)現(xiàn)最大等待時(shí)間

 更新時(shí)間:2023年03月28日 14:27:17   作者:愛我-中華  
這篇文章主要為大家詳細(xì)介紹了如何從源碼中了解FutureTask實(shí)現(xiàn)最大等待時(shí)間的方法,文中的示例代碼講解詳細(xì),感興趣的可以了解一下

預(yù)備知識(shí)

Java 線程掛起的常用方式有以下幾種

Thread.sleep(long millis):這個(gè)方法可以讓線程掛起一段時(shí)間,并釋放 CPU 時(shí)間片,等待一段時(shí)間后自動(dòng)恢復(fù)執(zhí)行。這種方式可以用來實(shí)現(xiàn)簡單的定時(shí)器功能,但如果不恰當(dāng)使用會(huì)影響系統(tǒng)性能。

Object.wait() 和 Object.notify() 或 Object.notifyAll():這是一種通過等待某個(gè)條件的發(fā)生來掛起線程的方式。wait() 方法會(huì)讓線程等待,直到其他線程調(diào)用了 notify() 或 notifyAll() 方法來通知它。這種方式需要使用 synchronized 或者 ReentrantLock 等同步機(jī)制來保證線程之間的協(xié)作和通信。

LockSupport.park() 和 LockSupport.unpark(Thread thread):這兩個(gè)方法可以讓線程掛起和恢復(fù)。park() 方法會(huì)使當(dāng)前線程掛起,直到其他線程調(diào)用了 unpark(Thread thread) 方法來喚醒它。這種方式比較靈活,可以根據(jù)需要控制線程的掛起和恢復(fù)。

先上結(jié)論

1.futureTask.get時(shí)通過LockSupport.park()掛起線程

2.在Thread.run() 方法中 調(diào)用 setException(ex)或set(result),然后調(diào)用LockSupport.unpark(t)喚醒線程。

示例-引入主題

public class FutureTaskDemo {
    public static void main(String[] args) {
        FutureTask<String> futureTask = new FutureTask<>(new Callable() {
            @Override
            public Object call() throws Exception {
                System.out.println("異步線程執(zhí)行");
                Thread.sleep(3000);//模擬線程執(zhí)行任務(wù)需要3秒
                return "ok";
            }
        });
        Thread t1 = new Thread(futureTask, "線程一");
        t1.start();

        try {
            //關(guān)鍵代碼
            String s = futureTask.get(2, TimeUnit.SECONDS); //最大等待線程2秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }
}

進(jìn)入futureTask.get(2, TimeUnit.SECONDS)

  public V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException {
        if (unit == null)
            throw new NullPointerException();
        int s = state;
        if (s <= COMPLETING &&
            (s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING) //重點(diǎn)awaitDone,即完成了最大等待,依然沒有結(jié)果就拋出異常邏輯
            throw new TimeoutException();
        return report(s);
    }

awaitDone返回線程任務(wù)執(zhí)行狀態(tài),即小于等于COMPLETING(任務(wù)正在運(yùn)行,等待完成)拋出異常TimeoutException

進(jìn)入(awaitDone(true, unit.toNanos(timeout)))原理分析

private int awaitDone(boolean timed, long nanos)
        throws InterruptedException {
        final long deadline = timed ? System.nanoTime() + nanos : 0L;
        WaitNode q = null;
        boolean queued = false;
        for (;;) {
            if (Thread.interrupted()) {
                removeWaiter(q);
                throw new InterruptedException();
            }

            int s = state;
            if (s > COMPLETING) {
                if (q != null)
                    q.thread = null;
                return s;
            }
            else if (s == COMPLETING) // cannot time out yet
                Thread.yield();
            else if (q == null)
                q = new WaitNode();
            else if (!queued)
                queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
                                                     q.next = waiters, q);
            else if (timed) {
                nanos = deadline - System.nanoTime();
                if (nanos <= 0L) {
                    removeWaiter(q);
                    return state;
                }
                LockSupport.parkNanos(this, nanos);
            }
            else
                LockSupport.park(this);
        }
    }

總體解讀awaitDone

利用自旋(for (;??)的方式 ,檢查state(任務(wù)狀態(tài))與waitNode(維護(hù)等待的線程),

第一步:首先檢查if (Thread.interrupted()) 線程是否被打斷(LockSupport.parkNanos掛起的線程被打斷不拋出異常),

第二步:判斷任務(wù)狀態(tài)與waitNode是否入隊(duì)+確定最大等待時(shí)間

? 若已完成(if (s > COMPLETING))返回任務(wù)狀態(tài)

? 若已完成(if (s == COMPLETING))-->表示正在完成,但尚未完成。則讓出 CPU,進(jìn)入就緒狀態(tài),等待其他線程的執(zhí)行

? 若if (q == null)==>創(chuàng)建等待等待節(jié)點(diǎn)

? 若if (!queued)==>表示上一步創(chuàng)建的節(jié)點(diǎn)沒有和當(dāng)前線程綁定,故綁定

? 最后else if (timed)與else,判斷最大等待時(shí)間

static final class WaitNode {
        volatile Thread thread;
        volatile WaitNode next;
        WaitNode() { thread = Thread.currentThread(); }
    }
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;
state可能轉(zhuǎn)換的過程 
    1.NEW -> COMPLETING -> NORMAL (成功完成)
    2.NEW -> COMPLETING -> EXCEPTIONAL (異常)
    3.NEW -> CANCELLED (任務(wù)被取消)
    4.NEW -> INTERRUPTING -> INTERRUPTED(任務(wù)被打斷)

關(guān)鍵代碼

LockSupport.park(this, nanos) ==內(nèi)部實(shí)現(xiàn)==> UNSAFE.park(false, nanos)();

? 即讓當(dāng)前線程堵塞直至指定的時(shí)間(nanos),該方法同Thread.sleep()一樣不會(huì)釋放持有的對(duì)象鎖,但不同的是Thread.sleep會(huì)被打斷(interrupted)并拋出異常,而LockSupport.park被打斷不會(huì)拋出異常,故在自旋時(shí)(for (;??)需判斷if (Thread.interrupted())線程是否被打斷(手動(dòng)拋出異常)。

線程運(yùn)行時(shí)state的變化軌跡

新建時(shí)利用構(gòu)造器設(shè)置state=NEW

 public FutureTask(Runnable runnable, V result) {
     this.callable = Executors.callable(runnable, result);
     this.state = NEW;   // 賦值狀態(tài)
 }

線程運(yùn)行時(shí)state可能變化軌跡

public void run() {
        ..........防止多次運(yùn)行stat()方法..............
        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;
                    setException(ex); //異常軌跡---> 見下分析
                }
                if (ran)
                    set(result); // 正常軌跡--->見下分析
            }
        } finally {
            runner = null;
    		//----最后結(jié)束---防止線程被打斷
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }

異常軌跡setException(ex)

protected void setException(Throwable t) {
    if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
        outcome = t;
        UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
        finishCompletion();
        //軌跡變化 2.NEW -> COMPLETING -> EXCEPTIONAL (異常)
    }
    //否則1: 3.NEW -> CANCELLED (任務(wù)被取消)
    //否則2: 4.NEW -> INTERRUPTING -> INTERRUPTED(任務(wù)被打斷)
}

正常軌跡 set(result);

1.NEW -> COMPLETING -> NORMAL (成功完成)

到此這篇關(guān)于詳解FutureTask如何實(shí)現(xiàn)最大等待時(shí)間的文章就介紹到這了,更多相關(guān)FutureTask最大等待時(shí)間內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一文搞懂Java創(chuàng)建線程的五種方法

    一文搞懂Java創(chuàng)建線程的五種方法

    本文主要為大家詳細(xì)介紹一下Java實(shí)現(xiàn)線程創(chuàng)建的五種常見方式,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)有一定的幫助,感興趣的可以跟隨小編學(xué)習(xí)一下
    2022-06-06
  • 用Java產(chǎn)生100個(gè)1-150間不重復(fù)數(shù)字

    用Java產(chǎn)生100個(gè)1-150間不重復(fù)數(shù)字

    這篇文章主要介紹了用Java產(chǎn)生100個(gè)1-150間不重復(fù)數(shù)字,需要的朋友可以參考下
    2017-02-02
  • Eclipse?IDE中如何設(shè)置JVM啟動(dòng)參數(shù)

    Eclipse?IDE中如何設(shè)置JVM啟動(dòng)參數(shù)

    這篇文章主要介紹了Eclipse?IDE中如何設(shè)置JVM啟動(dòng)參數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Java二叉樹查詢?cè)砩钊敕治鲋v解

    Java二叉樹查詢?cè)砩钊敕治鲋v解

    這篇文章主要介紹了Java二叉樹查詢?cè)?,二叉查找樹,又稱二叉排序樹,亦稱二叉搜索樹,是數(shù)據(jù)結(jié)構(gòu)中的一類。在一般情況下,查找效率比鏈表結(jié)構(gòu)要高
    2022-11-11
  • java利用pdfbox+poi往pdf插入數(shù)據(jù)

    java利用pdfbox+poi往pdf插入數(shù)據(jù)

    這篇文章主要給大家介紹了關(guān)于java利用pdfbox+poi如何往pdf插入數(shù)據(jù)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-02-02
  • 基于java構(gòu)造方法Vector刪除元素源碼分析

    基于java構(gòu)造方法Vector刪除元素源碼分析

    這篇文章主要介紹了基于java構(gòu)造方法中對(duì)Vector刪除元素的源碼分析,有需要的朋友可以借鑒參考下,希望可以有所幫助,祝大家早日升職加薪
    2021-09-09
  • mvc架構(gòu)實(shí)現(xiàn)商品的購買(二)

    mvc架構(gòu)實(shí)現(xiàn)商品的購買(二)

    這篇文章主要為大家詳細(xì)介紹了mvc架構(gòu)實(shí)現(xiàn)商品購買功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • Java根據(jù)url生成圖片、截圖效果

    Java根據(jù)url生成圖片、截圖效果

    文章詳細(xì)介紹了如何使用Java和Node.js結(jié)合Puppeteer庫根據(jù)URL截圖,并將圖片轉(zhuǎn)換為標(biāo)準(zhǔn)輸出流返回給Java程序,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2025-01-01
  • Mybatis使用Collection屬性的示例代碼

    Mybatis使用Collection屬性的示例代碼

    本文主要介紹了Mybatis使用Collection屬性的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • 淺談Java中Unicode的編碼和實(shí)現(xiàn)

    淺談Java中Unicode的編碼和實(shí)現(xiàn)

    這篇文章向大家介紹了Java編程中Unicode編碼及實(shí)現(xiàn)的相關(guān)內(nèi)容,列舉了幾個(gè)字符不同表達(dá)式的比較,以及Unicode平面映射的知識(shí),具有一點(diǎn)點(diǎn)參考價(jià)值,需要的朋友可以了解下。
    2017-10-10

最新評(píng)論

南皮县| 克东县| 庐江县| 儋州市| 嘉黎县| 辉县市| 乐平市| 济阳县| 延庆县| 彝良县| 镇平县| 曲靖市| 弋阳县| 二连浩特市| 池州市| 庆阳市| 元谋县| 孙吴县| 射洪县| 安平县| 汝阳县| 保山市| 乌拉特中旗| 陵川县| 广昌县| 岳阳县| 通江县| 花莲县| 迁西县| 木兰县| 达孜县| 青铜峡市| 定南县| 和平县| 和静县| 邯郸县| 鸡东县| 安平县| 乐亭县| 玉田县| 子洲县|