2017-02-28 12 views
6

Iは、Javaオブジェクトのリスト上どの単に反復ストリーム及び真/偽を返し使用方法を書かれている特定の条件が満たされているJavaの並列ストリーム近いスレッド

Javaメソッド:

boolean method(SampleObj sampleObj) { 

    List testList = invokeSomeMethod(); 
    int result = testList 
      .parallelStream() 
      .filter(listObj -> (listObj.getAttr() = 1)) 
      .count(listObj -> listObj.isAttr4()); 

    return (result > 10); 

} 

私が書かれています同じもののモックテストケース。テストケースを実行すると、テストは成功しますが、作成されたすべてのスレッドがシャットダウンされていないことを示すプロジェクトカスタムエラーが発生します。

私はtry-with-resourcesでストリームを使用しようとしても、それは役に立たなかった。

模擬試験:

@Test 
public void testSomeMethod() { 
    SampleObj sampleObj1 = new SampleObj(10, 20, 30, true); 
    SampleObj sampleObj2 = new SampleObj(10, 20, 30, true); 
    SampleObj sampleObj3 = new SampleObj(10, 20, 30, false); 
    SampleObj sampleObjTest = new SampleObj(10, 20, 30, true); 

    List<SampleObj> testList = new ArrayList<SampleObj>(); 
    testList.add(sampleObj1); 
    testList.add(sampleObj2); 
    testList.add(sampleObj3); 

    when(mockedAttribute.invokeSomeMethod()).thenReturn(nodeList); 

    ClassToBeTested classTest = createGenericMockRules(); 
    Assert.assertTrue(classTest.method(sampleObjTest)); 
} 

P.S.私はinvokeSomeMethod()が呼び出されたときに、私の模擬testListが返されることを確認するためにデバッグしました。

私が知る限り、Javaストリームは内部的に、作成したスレッドを閉じます。 これを間違って実装していますか?

+0

あなたは何を嘲笑していますか?テストケースを表示できますか? –

+0

コードスニペットを追加 – learningMyWayThru

+0

注釈として、 '== true'という表現は常に冗長です。 – chrylis

答えて

5

Javaストリームはスレッドを作成しないため、スレッドを廃棄しません。スレッドプールは内部的に使用されます。それは不明だが、それがcommon pool of the Fork/Join frameworkであることはよく知られている。

スレッドプールを使用する意図は、ジョブごとにスレッドを作成および廃棄するのではなく、スレッドがプールを管理できるようにすることです。スレッドの作成と破棄はコストと関連しています。これは、複数のジョブがその後エンキューされるときは避けるべきです。特に、スレッドを作成する既存のスレッドがない場合は、スレッドの作成時間がジョブの実行時間に追加されます。言い換えれば、スレッドはジョブよりも長く生きることが通常であり、意図されています。彼らは到着できる新しい仕事を待っている。

class documentation of ForkJoinPool状態:

静的commonPool()が利用可能であり、ほとんどのアプリケーションに適しています。共通プールは、指定されたプールに明示的にサブミットされていないForkJoinTaskによって使用されます。共通プールを使用すると、通常、リソースの使用量が減少します(そのスレッドは、使用されていない期間にゆっくり再利用され、その後の使用時に元に戻されます)。

スレッドは、スレッドが再利用される前にアイドル状態でなければならない時間を指定しません。それは、「ゆっくり」以外に、実装ごとに異なる場合もあります。現在の実装では、タイムアウト後にプールがスレッドの数を減らすのではなく、タイムアウトの後にアイドル状態のすべてのスレッドを終了させるため、タイムアウトの点でそれを言うことさえできないため、残りのスレッドは再び待機し、アイドル状態のスレッドがなくなるまで、プールがサイズを再び縮小するまで、タイムアウトします。言い換えれば、プールのスレッドが多いほど、すべてのスレッドがアイドル状態のときに最後のスレッドが再生されるまでに時間がかかります。

あなたは

while(ForkJoinPool.commonPool().getPoolSize()>0) 
    LockSupport.parkNanos(1000); 

を経由してすべてのスレッドの終了を待つためにテストを強制することができますが、これは、例えば、大幅にあなたのテストの実行時間を増やすことができます8つのコア/スレッドで1分の大きさを話す。より良い解決策は、内部的に使用されているプールによって作成されたスレッドの責任をコードに考慮する必要がない、「プロジェクトのカスタムエラー」チェックを再考することです。

そうしないと、使用時に同様のエラーが発生する可能性があります。非同期I/Oなど

+0

絶対に素晴らしい答え! – Eugene

関連する問題