gstackoverflow:
(私のPC上の)デッドロックに次のコードをリード:
public class Test {
static {
final int SUM = IntStream.range(0, 100)
.parallel()
.reduce((n, m) -> n + m)
.getAsInt();
}
public static void main(String[] args) {
System.out.println("Finished");
}
}
私は交換した場合でも、reduce
匿名クラスとラムダの引数をそれがデッドロックにはつながりません。
public class Test {
static {
final int SUM = IntStream.range(0, 100)
.parallel()
.reduce(new IntBinaryOperator() {
@Override
public int applyAsInt(int n, int m) {
return n + m;
}
})
.getAsInt();
}
public static void main(String[] args) {
System.out.println("Finished");
}
}
あなたはその状況を説明してもらえますか?
PS
私は、そのコード(前回とは異なるビット)が見つかりました:
public class Test {
static {
final int SUM = IntStream.range(0, 100)
.parallel()
.reduce(new IntBinaryOperator() {
@Override
public int applyAsInt(int n, int m) {
return sum(n, m);
}
})
.getAsInt();
}
private static int sum(int n, int m) {
return n + m;
}
public static void main(String[] args) {
System.out.println("Finished");
}
}
作品安定していません。ほとんどの場合、それが正常に終了時には言い訳をハング:
私は本当にないこの動作は安定していない理由を理解することができ。実際に私は、最初のコードスニペットと行動同じことを再テストします。だから、最新のコードは、最初の1に等しいです。
スレッドが使用されているかを理解するために私は、「ログ」を以下のコメントを追加しました:
public class Test {
static {
final int SUM = IntStream.range(0, 100)
.parallel()
.reduce((n, m) -> {
System.out.println(Thread.currentThread().getName());
return (n + m);
})
.getAsInt();
}
public static void main(String[] args) {
System.out.println("Finished");
}
}
アプリケーションが終了したときにケースのために成功した私は、次のログを参照してください。
main
main
main
main
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
main
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
main
main
main
main
main
main
main
main
main
main
main
main
main
main
main
main
main
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
main
main
main
main
main
main
main
main
main
main
main
main
main
main
main
main
main
main
main
main
main
main
main
main
main
main
main
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
Finished
PS 2
削減I Undestandは十分に複雑な操作です。私はその問題を示すために、単純な例を見つけました:
public class Test {
static {
System.out.println("static initializer: " + Thread.currentThread().getName());
final long SUM = IntStream.range(0, 2)
.parallel()
.mapToObj(i -> {
System.out.println("map: " + Thread.currentThread().getName() + " " + i);
return i;
})
.count();
}
public static void main(String[] args) {
System.out.println("Finished");
}
}
幸せな場合(まれなケース)のために、私は次の出力をseee:
static initializer: main
map: main 1
map: main 0
Finished
拡張ストリームの範囲のための幸せな場合の例:
static initializer: main
map: main 2
map: main 3
map: ForkJoinPool.commonPool-worker-2 4
map: ForkJoinPool.commonPool-worker-1 1
map: ForkJoinPool.commonPool-worker-3 0
Finished
デッドロックにつながる場合の例:
static initializer: main
map: main 1
また、デッドロックではなく、それぞれのスタートのためにつながります。
apangin:
違いは、ラムダ本体が同じで書かれているTest
、すなわち、合成方法、クラス
private static int lambda$static$0(int n, int m) {
return n + m;
}
第二のケースではインタフェースの実装は、に存在する異なる Test$1
クラス。並列ストリームのスレッドがの静的メソッドを呼び出すことはありませんのでTest
、したがって、に依存しないTest
初期化。