看下面的程序:
/**
* 功能产生一个整数
*/
public abstract class IntGenerator {
private boolean cancel = false;
public abstract int next();
public void cancel() {
this.cancel = true;
}
public boolean isCancel() {
return this.cancel;
}
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 校验是否为偶数
*
*/
public class EvenChecker implements Runnable {
private IntGenerator intGenerator;
private final int id ;
public EvenChecker(IntGenerator intGenerator,int ident) {
this.intGenerator = intGenerator;
this.id = ident;
}
@Override
public void run() {
while(!intGenerator.isCancel()) {
int val = intGenerator.next();
if (val % 2 != 0) {
System.out.println(val + " not even");
intGenerator.cancel();
}
}
}
public static void test(IntGenerator gp,int count) {
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < count; i++) {
exec.execute(new EvenChecker(gp,i));
}
exec.shutdown();
}
public static void test(IntGenerator gp) {
test(gp,10);
}
}
/**
* 校验产生的数据是否为偶数
*
*/
public class EvenGenerator extends IntGenerator {
/**
* currentEvenValue 是个类变量,会存在线程安全
*
*/
private int currentEvenValue = 0;
/**
* 这个方法没能使用同步,每个线程在任何时个都能进入方法体
*/
@Override
public int next() {
/** 因此会存在这样一种情况: 一个线程执行了下面行的++操作,
另一个执行return语句,这时next返回的不是一个偶数
*/
++currentEvenValue;
++currentEvenValue;
return currentEvenValue;
}
public static void main(String[] args) {
EvenChecker.test(new EvenGenerator());
}
}
在多数的情况下,你都能运行一下不为偶数的结果。在我的机器上,多数情况能运行出一个不为偶数的结果,有时不能输出一个结果。
解决这个问题的方法如下:
@Override
public synchronized int next() {
/** 因此会存在这样一种情况: 一个线程执行了下面行的++操作,
另一个执行return语句,这时next返回的不是一个偶数
*/
++currentEvenValue;
++currentEvenValue;
return currentEvenValue;
}
next() 加上关键字 synchronized ,表示next() 方法是同步方法,任何时刻只能允许一个线程进行next()方法体。