这是我的代码,运行我的代码时输出都是不同的。有时会通知所有三个阅读器,输出为:
等待计算...
等待计算...
等待计算...
已完成
总计为:4950Thread-1
总数是:4950Thread-2
总数是:4950线程-0
有时只会通知两个或一个读者。
问题是什么?
class Reader extends Thread {
Calculator c;
public Reader(Calculator calc) {
c = calc;
}
public void run() {
synchronized (c) {
try {
System.out.println("Waiting for calculation...");
c.wait();
} catch (InterruptedException e) {
}
System.out.println("Total is: " + c.total +Thread.currentThread().getName());
}
}
public static void main(String[] args) {
Calculator calculator = new Calculator();
new Reader(calculator).start();
new Reader(calculator).start();
new Reader(calculator).start();
new Thread(calculator).start();
}
}
class Calculator implements Runnable {
int total;
public void run() {
synchronized (this) {
for (int i = 0; i < 100; i++) {
total += i;
}
System.out.println("Finished");
notifyAll();
}
}
}
根据元发布,这个问题被认为是重复的,但是被欺骗的两个“重复”根本不适用。 How to use wait and notify in Java?提醒用户,如果您确实要等待同一对象,则必须在该对象上进行同步。但是此解决方案已在执行此操作。 Java: notify() vs. notifyAll() all over again提醒用户
notify
和notifyAll
之间的差异,甚至与问题无关。 最佳答案
我能够重现该问题-基本上,如果您的计算机速度太快或调度不正确,计算器可能会在读者有机会进行同步和等待之前完成操作。
c:\ files \ j> java Reader
等待计算...
等待计算...
已完成
等待计算...
总数是:4950Thread-2
总数是:4950线程-0
为避免这种情况,您应该在执行计算之前验证所有阅读器均已准备就绪。
c:\ files \ j> java Reader
等待计算...
等待读者...目前1
等待计算...
等待计算...
已完成
总计为:4950Thread-1
总数是:4950Thread-2
总数是:4950线程-0
这是我的代码
import java.util.concurrent.atomic.AtomicInteger; // corsiKa added import
class Reader extends Thread {
static class Calculator implements Runnable {
int total;
AtomicInteger readers = new AtomicInteger(0); // corsiKa added atomicinteger
public void run() {
// corsiKa added while
while(readers.get() < 3) {
System.out.println("Waiting for readers... currently " + readers.get());
try { Thread.sleep(100); } catch(InterruptedException e) { }
}
synchronized (this) {
for (int i = 0; i < 100; i++) {
total += i;
}
System.out.println("Finished");
notifyAll();
}
}
}
Calculator c;
public Reader(Calculator calc) {
c = calc;
}
public void run() {
synchronized (c) {
try {
c.readers.incrementAndGet(); // corsiKa added increment
System.out.println("Waiting for calculation...");
c.wait();
} catch (InterruptedException e) {
}
System.out.println("Total is: " + c.total +Thread.currentThread().getName());
}
}
public static void main(String[] args) {
Calculator calculator = new Calculator();
new Reader(calculator).start();
new Reader(calculator).start();
new Reader(calculator).start();
new Thread(calculator).start();
}
}