Java 8 上的同步和 ExecutorService
synchronized and ExecutorService on Java 8
我的预期是程序会 return 输出“1000”。
但是,程序每次执行都会出现不同的输出。
计数器 class 的 increment() 方法已同步。只有这样才能避免竞争读数吗?
让它计算 1000 个增量的正确方法是什么?
package app;
public class Counter {
private Integer value;
public Counter(int initialValue) {
value = initialValue;
}
public synchronized void increment() {
value = value + 1;
}
public int getValue() {
return value;
}
}
package app;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
Counter contador = new Counter(0);
ExecutorService executor = Executors.newFixedThreadPool(10);
for(int i = 0; i < 1000; i++) {
executor.submit(() -> {
contador.increment();
});
}
System.out.println(contador.getValue());
}
}
您的问题的答案是您没有等待所有 Runnables 完成后再打印 contador 的值。
所以有时只调用了 20 次增量调用,有时调用了 50 次,等等
编辑:
仔细观察,我认为您的线程安全性存在潜在问题。您已同步增量值。 getValue 方法应该匹配吗?
比如线程A在自增过程中,线程B在调用getValue时应该看到什么?它应该看到旧值,还是应该等到线程 A 完成后再获取最新值?
你的逻辑没问题。
问题是您在线程完成递增之前打印了计数器的值。
将您的代码更改为:
for(int i = 0; i < 1000; i++) {
executor.submit(() -> {
contador.increment();
});
}
executor.shutdown(); //Shut down the executor
//Wait until the threads have stopped. A maximum of 1 minute is more than enough
executor.awaitTermination(1, TimeUnit.MINUTES);
System.out.println(contador.getValue()); //prints 1000
这是您的主要方法的外观:
public static void main(String[] args) {
Counter contador = new Counter(0);
ExecutorService executor = Executors.newFixedThreadPool(10);
for(int i = 0; i < 1000; i++) {
executor.submit(() -> {
contador.increment();
});
}
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
}
System.out.println(contador.getValue());
}
我的预期是程序会 return 输出“1000”。
但是,程序每次执行都会出现不同的输出。
计数器 class 的 increment() 方法已同步。只有这样才能避免竞争读数吗?
让它计算 1000 个增量的正确方法是什么?
package app;
public class Counter {
private Integer value;
public Counter(int initialValue) {
value = initialValue;
}
public synchronized void increment() {
value = value + 1;
}
public int getValue() {
return value;
}
}
package app;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
Counter contador = new Counter(0);
ExecutorService executor = Executors.newFixedThreadPool(10);
for(int i = 0; i < 1000; i++) {
executor.submit(() -> {
contador.increment();
});
}
System.out.println(contador.getValue());
}
}
您的问题的答案是您没有等待所有 Runnables 完成后再打印 contador 的值。
所以有时只调用了 20 次增量调用,有时调用了 50 次,等等
编辑:
仔细观察,我认为您的线程安全性存在潜在问题。您已同步增量值。 getValue 方法应该匹配吗?
比如线程A在自增过程中,线程B在调用getValue时应该看到什么?它应该看到旧值,还是应该等到线程 A 完成后再获取最新值?
你的逻辑没问题。
问题是您在线程完成递增之前打印了计数器的值。
将您的代码更改为:
for(int i = 0; i < 1000; i++) {
executor.submit(() -> {
contador.increment();
});
}
executor.shutdown(); //Shut down the executor
//Wait until the threads have stopped. A maximum of 1 minute is more than enough
executor.awaitTermination(1, TimeUnit.MINUTES);
System.out.println(contador.getValue()); //prints 1000
这是您的主要方法的外观:
public static void main(String[] args) {
Counter contador = new Counter(0);
ExecutorService executor = Executors.newFixedThreadPool(10);
for(int i = 0; i < 1000; i++) {
executor.submit(() -> {
contador.increment();
});
}
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
}
System.out.println(contador.getValue());
}