Fork Join中的呼叫原理

2021-07-08 13:55:38 字數 3450 閱讀 7980

錯誤程式

public class calculator extends recursivetask 

@override

protected integer compute()

}else

return sum;

}}

(1)fork

1.基本作用

將任務放入任務佇列隊尾

2.原始碼

public final forkjointaskfork()
該方法屬於:forkjointask,也就是說this指向任務本身,將任務新增到任務佇列末尾

因為執行forkjointask的執行緒就是forkjoinworkerthread,所以可以呼叫其中的pushtask方法

/**

* pushes a task. call only from this thread.

** @param t the task. caller must ensure non-null.

*/final void pushtask(forkjointask<?> t)

}

其中有個成員變數queue,用來儲存和本執行緒對應的任務佇列

定義:

forkjointask<?> queue;

初始化:

protected void onstart()
接著繼續看pushtask

if ((s -= queuebase) <= 2)

pool.signalwork();

就是說當任務佇列中只有乙個任務時,從執行緒池中呼叫執行緒執行

(2)join

1.基本作用

阻塞當前執行緒,直到本任務執行完畢(相當於forkjointask版的thread.join)

2.原始碼

public final v join()
主要是為了看返回值,接著看dojoin

private int dojoin()  catch (throwable rex) 

if (completed)

return setcompletion(normal);

}return w.jointask(this);

}else

return externalawaitdone();

}

這裡先通過status判斷狀態

volatile int status; // accessed directly by pool and workers

private static final int normal = -1;

private static final int cancelled = -2;

private static final int exceptional = -3;

private static final int signal = 1;

也就是說<0的是已經執行完畢的,

這對於竊取非常重要

然後通過unpushtask取任務然後執行,看下unpushtask

final boolean unpushtask(forkjointask<?> t) 

return false;

}

注意其中的

--s,也就是

說是從佇列尾取的任務

(3)分析

left.fork();

right.fork();

sum = left.join() + right.join();

由上面可知,這段**的意思就是:

1.把left放入任務佇列,right放入任務佇列。此時right在隊尾,left在倒數第二個

2.left.join(),因為當前right在隊尾,所以說取不出來!!!因而執行緒就會阻塞

正確的是呼叫invokeall,看下invokeall

public static void invokeall(forkjointask<?> t1, forkjointask<?> t2)
也就是說先把t2加入佇列中,然後直接執行t1,接著對t2執行join

對應上例就是:把right放入佇列尾部,然後left開始執行,最後對right進行join,直到left執行完畢才能執行(當然right可能被其他執行緒竊取,這樣通過狀態判斷就直接返回了)

更一般的

public static void invokeall(forkjointask<?>... tasks) 

else if (i != 0)

t.fork();

else if (t.doinvoke() < normal && ex == null)

ex = t.getexception();

}for (int i = 1; i <= last; ++i)

}if (ex != null)

unsafe.throwexception(ex);

}

可以看到 i != 0 才進行fork,也就是說佇列中第乙個都是直接執行的,其他的以此fork,fork之後的任務之後進行join

(4)invoke

1.基本作用

直接執行任務

2.原始碼

public final v invoke()
再看下doinvoke

private int doinvoke()  catch (throwable rex) 

if (completed)

return setcompletion(normal);

else

return dojoin();

}

其中的exec()在recursivetask中

protected final boolean exec()
在recursiveaction中

protected final boolean exec()
也就是說直接執行了

JAVA中的Fork Join框架

fork join框架是executorservice介面的乙個實現,可以幫助開發人員充分利用多核處理器的優勢,編寫出並行執行的程式,提高應用程式的效能 設計的目的是為了處理那些可以被遞迴拆分的任務。fork join框架與其它executorservice的實現類相似,會給執行緒池中的執行緒分發任...

jquery中鏈式呼叫原理

1 鏈式呼叫 mybtn css width 100px css height 100px css background red 2 在對屬性進行操作時建議使用json形式控制樣式 mybtn css 3 事件中this的指向 事件中this的指向 jquery中提示了乙個方法,該方法可以將原生js...

jQuery中鏈式呼叫原理

1 鏈式呼叫 1 mybtn css width 100px 23 css height 100px 45 css background red 2 在對屬性進行操作時建議使用json形式控制樣式 1 mybtn css 3 事件中this的指向 事件中this的指向 jquery中提示了乙個方法,...