Java 使用并行流阻止所有其他线程
我有一个小程序,它可以启动4个线程,每个线程的数量为偶数到20。 我只对其中一个线程执行了睡眠,但似乎所有其他线程都被阻塞,等待阻塞的线程恢复 为什么启用并行流处理会导致这种行为Java 使用并行流阻止所有其他线程,java,Java,我有一个小程序,它可以启动4个线程,每个线程的数量为偶数到20。 我只对其中一个线程执行了睡眠,但似乎所有其他线程都被阻塞,等待阻塞的线程恢复 为什么启用并行流处理会导致这种行为 public class Program { static int first; public static void main(String[] a) throws InterruptedException { new Program().runTask
public class Program {
static int first;
public static void main(String[] a) throws InterruptedException {
new Program().runTasks();
}
private void runTasks() throws InterruptedException {
int value = 20;
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> numberOfEvens(value));
first++;
executorService.execute(() -> numberOfEvens(value));
executorService.execute(() -> numberOfEvens(value));
executorService.execute(() -> numberOfEvens(value));
executorService.shutdown();
}
private void numberOfEvens(int val) {
System.out.println(IntStream.range(1, val).parallel().filter(this::isEven).count());
}
private void delay(int d) {
try {
Thread.sleep(d);
} catch (InterruptedException ex) {
// Do Nothing
}
}
private boolean isEven(int n) {
if (first == 1)
delay(1000);
return n % 2 == 0;
}
}
您的问题是假设静态在启动后仍然对线程可用 创建第一个lambda时,第一个变量的值可能为零,但不久之后,几乎可以肯定,在第一次调用delay时,它的值为1 这就达到了您想要的效果-打印延迟为预期的20倍:
public static class Program {
public static void main(String[] a) throws InterruptedException {
new Program().runTasks();
}
private void runTasks() throws InterruptedException {
int value = 20;
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> numberOfEvens(value, true));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.shutdown();
}
private void numberOfEvens(int val, boolean first) {
System.out.println(IntStream.range(1, val).parallel().filter(n -> isEven(n, first)).count());
}
private void delay(int d) {
try {
System.out.println("Delaying");
Thread.sleep(d);
} catch (InterruptedException ex) {
// Do Nothing
}
}
private boolean isEven(int n, boolean first) {
if (first) {
delay(1000);
}
return n % 2 == 0;
}
}
您的问题是假设静态在启动后仍然对线程可用 创建第一个lambda时,第一个变量的值可能为零,但不久之后,几乎可以肯定,在第一次调用delay时,它的值为1 这就达到了您想要的效果-打印延迟为预期的20倍:
public static class Program {
public static void main(String[] a) throws InterruptedException {
new Program().runTasks();
}
private void runTasks() throws InterruptedException {
int value = 20;
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> numberOfEvens(value, true));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.execute(() -> numberOfEvens(value, false));
executorService.shutdown();
}
private void numberOfEvens(int val, boolean first) {
System.out.println(IntStream.range(1, val).parallel().filter(n -> isEven(n, first)).count());
}
private void delay(int d) {
try {
System.out.println("Delaying");
Thread.sleep(d);
} catch (InterruptedException ex) {
// Do Nothing
}
}
private boolean isEven(int n, boolean first) {
if (first) {
delay(1000);
}
return n % 2 == 0;
}
}
您从不首先初始化,因此它从sun文档开始为0:
声明字段时并不总是需要赋值。
已声明但未初始化的字段将设置为
编译器的合理默认值。一般来说,这是默认的
将为零或null,具体取决于数据类型。依靠这些
然而,默认值通常被认为是糟糕的编程
风格
因此,当您执行first++时,它的值为1,因此所有其他线程都处于休眠状态。
将first初始化为1可以解决此问题,如下所示:
static int first = 1;
默认值
您从不首先初始化,因此它从sun文档开始为0:
声明字段时并不总是需要赋值。
已声明但未初始化的字段将设置为
编译器的合理默认值。一般来说,这是默认的
将为零或null,具体取决于数据类型。依靠这些
然而,默认值通常被认为是糟糕的编程
风格
因此,当您执行first++时,它的值为1,因此所有其他线程都处于休眠状态。
将first初始化为1可以解决此问题,如下所示:
static int first = 1;
默认值