中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

FutureTask怎么實現最大等待時間

發布時間:2023-03-28 15:47:14 來源:億速云 閱讀:89 作者:iii 欄目:開發技術

這篇文章主要介紹了FutureTask怎么實現最大等待時間的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇FutureTask怎么實現最大等待時間文章都會有所收獲,下面我們一起來看看吧。

預備知識

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

Thread.sleep(long millis):這個方法可以讓線程掛起一段時間,并釋放 CPU 時間片,等待一段時間后自動恢復執行。這種方式可以用來實現簡單的定時器功能,但如果不恰當使用會影響系統性能。

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

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

先上結論

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

2.在Thread.run() 方法中 調用 setException(ex)或set(result),然后調用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("異步線程執行");
                Thread.sleep(3000);//模擬線程執行任務需要3秒
                return "ok";
            }
        });
        Thread t1 = new Thread(futureTask, "線程一");
        t1.start();

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

進入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) //重點awaitDone,即完成了最大等待,依然沒有結果就拋出異常邏輯
            throw new TimeoutException();
        return report(s);
    }

awaitDone返回線程任務執行狀態,即小于等于COMPLETING(任務正在運行,等待完成)拋出異常TimeoutException

進入(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(任務狀態)與waitNode(維護等待的線程),

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

第二步:判斷任務狀態與waitNode是否入隊+確定最大等待時間

若已完成(if (s > COMPLETING))返回任務狀態

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

若if (q == null)==>創建等待等待節點

若if (!queued)==>表示上一步創建的節點沒有和當前線程綁定,故綁定

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

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可能轉換的過程 
    1.NEW -> COMPLETING -> NORMAL (成功完成)
    2.NEW -> COMPLETING -> EXCEPTIONAL (異常)
    3.NEW -> CANCELLED (任務被取消)
    4.NEW -> INTERRUPTING -> INTERRUPTED(任務被打斷)

關鍵代碼

LockSupport.park(this, nanos) ==內部實現==> UNSAFE.park(false, nanos)();

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

線程運行時state的變化軌跡

新建時利用構造器設置state=NEW

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

線程運行時state可能變化軌跡

public void run() {
        ..........防止多次運行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;
    		//----最后結束---防止線程被打斷
            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 (任務被取消)
    //否則2: 4.NEW -> INTERRUPTING -> INTERRUPTED(任務被打斷)
}

正常軌跡 set(result);

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

關于“FutureTask怎么實現最大等待時間”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“FutureTask怎么實現最大等待時間”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

农安县| 个旧市| 临桂县| 饶阳县| 革吉县| 怀化市| 清苑县| 衡南县| 右玉县| 潮州市| 科技| 宝山区| 天门市| 宜宾市| 怀仁县| 信丰县| 武定县| 施甸县| 积石山| 张掖市| 长顺县| 合江县| 韶关市| 安仁县| 县级市| 乐山市| 濮阳市| 介休市| 拉萨市| 通河县| 新疆| 郎溪县| 霍城县| 隆昌县| 神池县| 富平县| 东台市| 资兴市| 班玛县| 黑龙江省| 商南县|