亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Java ForkJoinPool - 隊列中的任務順序

Java ForkJoinPool - 隊列中的任務順序

呼啦一陣風 2021-09-29 16:32:05
我想了解在 Java fork-join 池中處理任務的順序。到目前為止,我在文檔中找到的唯一相關信息是關于名為“asyncMode”的參數,“如果此池對從未加入的分叉任務使用本地先進先出調度模式,則為真” .我對這句話的理解是每個worker都有自己的任務隊列;工作人員從自己隊列的前面獲取任務,如果自己的隊列為空,則從其他工作人員的隊列后面竊取任務;如果 asyncMode 為真(相應的假),工作人員會將新分叉的任務添加到他們自己隊列的后面(相應的前面)。如果我的解釋有誤,請糾正我!現在,這提出了幾個問題:1)加入的分叉任務的順序是什么?我的猜測是,當一個任務被分叉時,它會被添加到工作人員的隊列中,如我上面的解釋中所述。現在,假設任務已加入...如果在調用 join 時任務尚未啟動,則調用 join 的 worker 會將任務從隊列中拉出并立即開始處理它。如果在調用 join 時該任務已被另一個 worker 竊取,則調用 join 的 worker 將同時處理其他任務(按照我上面解釋中描述的獲取任務的順序),直到它被加入已經被偷走它的工人完成了。這個猜測是基于用打印語句編寫簡單的測試代碼,并觀察改變連接調用順序影響任務處理順序的方式。有人可以告訴我我的猜測是否正確?2) 外部提交的任務排序是什么?根據這個問題的答案,fork-join 池不使用外部隊列。(順便說一下,我正在使用 Java 8。)那么我是否理解在外部提交任務時,該任務會被添加到隨機選擇的工作隊列中?如果是,外部提交的任務是加在隊列的后面還是前面?最后,這取決于任務是通過調用 pool.execute(task) 還是通過調用 pool.invoke(task) 提交?這是否取決于調用 pool.execute(task) 或 pool.invoke(task) 的線程是外部線程還是此 fork-join 池中的線程?
查看完整描述

1 回答

?
皈依舞

TA貢獻1851條經驗 獲得超3個贊

你的猜測是正確的,你完全正確。正如您在“實施概述”中所讀到的那樣。

 * Joining Tasks

 * =============

 *

 * Any of several actions may be taken when one worker is waiting

 * to join a task stolen (or always held) by another.  Because we

 * are multiplexing many tasks on to a pool of workers, we can't

 * just let them block (as in Thread.join).  We also cannot just

 * reassign the joiner's run-time stack with another and replace

 * it later, which would be a form of "continuation", that even if

 * possible is not necessarily a good idea since we may need both

 * an unblocked task and its continuation to progress.  Instead we

 * combine two tactics:

 *

 *   Helping: Arranging for the joiner to execute some task that it

 *      would be running if the steal had not occurred.

 *

 *   Compensating: Unless there are already enough live threads,

 *      method tryCompensate() may create or re-activate a spare

 *      thread to compensate for blocked joiners until they unblock.

2.ForkJoinPool.invoke和ForkJoinPool.join在提交任務的方式上是完全一樣的。你可以在代碼中看到


    public <T> T invoke(ForkJoinTask<T> task) {

        if (task == null)

            throw new NullPointerException();

        externalPush(task);

        return task.join();

    }

    public void execute(ForkJoinTask<?> task) {

        if (task == null)

            throw new NullPointerException();

        externalPush(task);

    }

在 externalPush 中,您可以看到使用 ThreadLocalRandom 將任務添加到隨機選擇的工作隊列中。此外,它使用推送方法進入隊列的頭部。


    final void externalPush(ForkJoinTask<?> task) {

        WorkQueue[] ws; WorkQueue q; int m;

        int r = ThreadLocalRandom.getProbe();

        int rs = runState;

        if ((ws = workQueues) != null && (m = (ws.length - 1)) >= 0 &&

            (q = ws[m & r & SQMASK]) != null && r != 0 && rs > 0 &&

            U.compareAndSwapInt(q, QLOCK, 0, 1)) {

            ForkJoinTask<?>[] a; int am, n, s;

            if ((a = q.array) != null &&

                (am = a.length - 1) > (n = (s = q.top) - q.base)) {

                    int j = ((am & s) << ASHIFT) + ABASE;

                U.putOrderedObject(a, j, task);

                U.putOrderedInt(q, QTOP, s + 1);

                U.putIntVolatile(q, QLOCK, 0);

                if (n <= 1)

                    signalWork(ws, q);

                return;

            }

            U.compareAndSwapInt(q, QLOCK, 1, 0);

        }

        externalSubmit(task);

    }

我不確定你的意思是什么:


這是否取決于調用 pool.execute(task) 或 pool.invoke(task) 的線程是外部線程還是此 fork-join 池中的線程?


查看完整回答
反對 回復 2021-09-29
  • 1 回答
  • 0 關注
  • 330 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號