Java併發程式設計指南(五) Fork Join框架

2021-08-16 23:24:15 字數 4337 閱讀 7874

這個框架被設計用來解決可以使用分而治之技術將任務分解成更小的問題。在乙個任務中,檢查你想要解決問題的大小,如果它大於乙個既定的大小,把它分解成更小的任務,然後用這個框架來執行。

這個框架基於以下兩種操作:

work-stealing演算法:

當乙個任務正在等待它使用join操作建立的子任務的結 束時,執行這個任務的執行緒(工作執行緒)查詢其他未被執行的任務並開始它的執行。通過這種方式,執行緒充分利用它們的執行時間,從而提高了應用程式的效能。

fork/join框架執行的任務有以下侷限性:

fork/join框架的核心是由以下兩個類:

//1.建立類product,將用來儲存產品的名稱和**。

class product

public void setname(string name)

public double getprice()

public void setprice(double price)

}//2.建立productlistgenerator類,用來產生隨機產品的數列。

class productlistgenerator

return ret;

}}//3.建立task類,指定它繼承recursiveaction類。

class task extends recursiveaction

//14.實現compute()方法 ,該方法將實現任務的邏輯。

@override

protected void compute() else

}//17.實現updateprices()方法。這個方法更新產品佇列中位於first值和last值之間的產品。

private void updateprices()

}}class main5 catch (interruptedexception e)

} while (!task.isdone());

//24.使用shutdown()方法關閉這個池。

pool.shutdown();

//25.使用iscompletednormally()方法檢查假設任務完成時沒有出錯,在這種情況下,寫入一條資訊到控制台。

if (task.iscompletednormally())

//26.在增長之後,所有產品的**應該是12。將**不是12的所有產品的名稱和**寫入到控制台,用來檢查它們錯誤地增長它們的**。

for (int i = 0; i < products.size(); i++)

}//27.寫入一條資訊到控制台表明程式的結束。

system.out.println("main: end of the program.\n");}}

//1.建立乙個document類,它將產生用來模擬文件的字串的二維陣列。

class document ;

//3.實現generatedocument()方法。它接收以下引數:行數、每行的單詞數。這個例子返回乙個字串二維陣列,來表示將要查詢的單詞。

public string generatedocument(int numlines, int numwords, string word) }}

//6.將單詞出現的次數寫入控制台,並返回生成的二維陣列。

return document;

}}//7.建立乙個documenttask類,指定它繼承recursivetask類,並引數化為integer型別。該類將實現統計單詞在一組行中出現的次數的任務。

class documenttask extends recursivetask

//10.實現compute()方法。如果屬性end和start的差小於10,那麼這個任務統計單詞位於行在呼叫processlines()方法的這些位置中出現的次數。

@override

protected integer compute() else catch (interruptedexception | executionexception e)

}return result;

}//13.實現processlines()方法。它接收以下引數:字串二維陣列、start屬性、end屬性、任務將要查詢的word屬性。

private integer processlines(string document, int start, int end, string word)

//15.在那個數列中使用invokeall()執行所有任務。

invokeall(tasks);

//16.合計所有這些任務返回的值,並返回這個結果。

int result = 0;

for (int i = 0; i < tasks.size(); i++) catch (interruptedexception | executionexception e)

}return result;

}}//18.建立linetask類,指定它繼承recursivetask類,並引數化為integer型別。這個類將實現統計單詞在一行中出現的次數的任務。

class linetask extends recursivetask

//21.實現這個類的compute()方法。如果屬性end和start之差小於100,這個任務在行中由start和end屬性使用count()方法決定的片斷中查詢單詞。

@override

protected integer compute() else catch (interruptedexception | executionexception e)

}return result;

}//24.實現count()方法。它接收以下引數:完整行的字串陣列、start屬性、end屬性、任務將要查詢的word屬性。

private integer count(string line, int start, int end, string word)

}//26.為了顯示示例的執行,令任務睡眠10毫秒。

try catch (interruptedexception e)

//27.返回counter變數的值。

return counter;

}//28.實現groupresults()方法。它合計兩個數的值,並返回這個結果。

private integer groupresults(integer number1, integer number2)

}//29.實現示例的主類,通過建立main類,並實現main()方法。

class main6 catch (interruptedexception e)

} while (!task.isdone());

//34.使用shutdown()方法關閉這個池。

pool.shutdown();

//35.使用awaittermination()方法等待任務的結束。

try catch (interruptedexception | executionexception e)

//36.列印單詞在文件中出現的次數。檢查這個數是否與documentmock類中寫入的數一樣。

try catch (interruptedexception | executionexception e) }}

使用fork()方法把task物件提交給池,任務將會被非同步的執行,使用join()方法等待已提交到池的所有任務的結束。

在forkjointask類的compute()方法中,你不能丟擲任何已檢查異常,因為在這個方法的實現中,它沒有包含任何丟擲(異常)宣告。你必須包含必要的**來處理異常。但是,你可以丟擲(或者它可以被任何方法或使用內部方法的物件丟擲)乙個未檢查異常。forkjointask和forkjoinpool類的行為與你可能的期望不同。程式不會結束執行,並且你將不會在控制台看到任何關於異常的資訊。它只是被吞沒,好像它沒丟擲(異常)。你可以使用forkjointask類的一些方法,得知乙個任務是否丟擲異常及其異常種類。

使用iscompletedabnormally()方法,檢查這個任務或它的子任務是否已經丟擲異常。在這種情況下,將丟擲的異常寫入到控制台。使用forkjointask類的getexception()方法獲取那個異常。

你還可以使用forkjointask類的completeexceptionally()方法將異常資訊返回。

當你在乙個forkjoinpool類中執行forkjointask物件,在它們開始執行之前,你可以取消執行它們。forkjointask類提供cancel()方法用於這個目的。當你想要取消乙個任務時,有一些點你必須考慮一下,這些點如下:

JAVA併發程式設計

通過常量字串 string 來呼叫 wait 或 notify 方法所導致的問題是,jvm 編譯器會在內部自動將內容相同的 string 轉變為相同的物件。這意味著,即便你建立了兩個不同的 mywaitnotify 例項,他們內部的 mymonitorobject 變數也會指向相同的 string ...

Java併發程式設計

執行緒之間通訊 1.加鎖 object.wait 釋放鎖 object.notify 與sychronized 聯合使用,object lock new object sychronized lock sychronized lock 2.改進 無需加鎖並發包下 countdownlatch.awa...

併發程式設計(五) CAS

在atomic包中,大多數類都是借助unsafe類來實現的,如以下 public static atomicinteger count new atomicinteger 0 private static void add incrementandget 方法的實現如下 public final i...