import java.math.BigInteger;
class Numbers {
final static int NUMBER = 2;
final static int POWER = 4;
static long msecs;
static BigInteger result;
static Boolean done = false;
public static void main(String[] args) {
BigInteger number = BigInteger.valueOf(NUMBER);
result = number;
//Boolean done = false;
Runnable pow = () -> {
System.out.println(number + " pow " + POWER + " = " + number.pow(POWER));
synchronized (done) {
done = true;
done.notifyAll();
}
};
Runnable sum = () -> {
for(int i = 2; i<POWER; i=i*i) {
result = result.multiply(result);
}
System.out.println(number + " sum " + POWER + " = " + result);
synchronized (done) {
done = true;
done.notifyAll();
}
};
Runnable time = () -> {
for(msecs = 0; true; msecs++) {
try {
Thread.sleep(1);
} catch(InterruptedException e) {
//nic
}
}
};
Thread timet = new Thread(time);
Thread sumt = new Thread(sum);
Thread powt = new Thread(pow);
timet.start();
powt.start();
synchronized (done) {
while(!done) {
try {
done.wait();
} catch (InterruptedException e) {
//nic
}
}
}
timet.interrupt();
powt.interrupt();
System.out.println("Pow time " + msecs + " msecs.");
done = false;
timet.start();
sumt.start();
try {
synchronized (done) {
while (!done) {
done.wait();
}
}
} catch (InterruptedException e) {
//nic
}
timet.interrupt();
sumt.interrupt();
System.out.println("Sum time " + msecs + " msecs.");
}
}
我想检查这两种方法之间的时差,但done.notifyAll()
不断抛出IllegalMonitorStateException
。
答案 0 :(得分:8)
问题出在这里:
image_params
由于您要为synchronized (done) {
done = true;//<---problem
done.notifyAll();
}
分配新值,这意味着您正在done
上执行notifyAll
,但您的同步块正在使用Boolean.TRUE
的监视器。由于Boolean.FALSE
要求线程拥有执行它的对象的监视器,因此它会抛出notifyAll
。
因此,请勿更改同步对象的值。同时避免在可用于所有类(公共常量/文字)的对象上进行同步,因为您冒着其他人会有相同想法的风险,并且还会在同步中使用它们,这可能会让您感到痛苦。
锁只能从类中属于它们才能访问。以Jon Skeet(What is the difference between synchronized on lockObject and using this as the lock?)为例,并在您自己的同步
IllegalMonitorStateException
答案 1 :(得分:3)
我想我知道发生了什么......如果您阅读了Object的关于Object.notifyAll()的文档
IllegalArgumentException - if the value of timeout is negative.
IllegalMonitorStateException - if the current thread is not the owner of the object's monitor.
InterruptedException - if any thread interrupted the current thread before or while the current thread was waiting for a notification. The interrupted status of the current thread is cleared when this exception is thrown.
因此,我认为你需要一个新的Object作为锁来访问你的完成。
例如:a private final Object doneLock = new Object()
。您现在可以在Done
上进行同步,而不是在doneLock
上进行同步。我应该是最终的,因为锁需要是私人的和最终的,所以他们无法在外面访问。
例如,
synchronize(doneLock) {
done = true;
doneLock.notifyAll();
}