虽然我理解了线程间通信的要点以及监视器上等待和通知的使用,以确保Put / Get操作同步 - 我试图理解为什么我们需要 Thread.sleep() ,在我们有一个工作的等待/通知机制时,生产者和消费者的代码如下?如果我删除thread.sleep() - 输出就会变成地狱!
import java.io.*;
import java.util.*;
public class Test {
public static void main(String argv[]) throws Throwable {
Holder h = new Holder();
Thread p = new Thread(new Producer(h), "Producer");
Thread c = new Thread(new Consumer(h), "Consumer");
p.start();
c.start();
}
}
class Holder {
int a;
volatile boolean hasPut;
public synchronized void put(int i) {
while (hasPut) {
try {
System.out.println("The thread " + Thread.currentThread().getName() + " Going ta sleep...");
wait(1000);
} catch(Exception e) {
e.printStackTrace();
}
}
this.a = i;
hasPut = true;
notifyAll();
}
public synchronized int get() {
while (!hasPut) {
try {
System.out.println("The thread " + Thread.currentThread().getName() + " Going ta sleep...");
wait(1000);
} catch(Exception e) {
e.printStackTrace();
}
}
hasPut = false;
notifyAll();
return this.a;
}
}
class Producer implements Runnable {
Holder h;
public Producer(Holder h) {
this.h = h;
}
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("Putting : "+i);
h.put(i);
try {
Thread.sleep(10);
} catch (InterruptedException ie) {
}
}
}
}
class Consumer implements Runnable {
Holder h;
public Consumer(Holder h) {
this.h = h;
}
public void run() {
for (int i = 0; i < 1000; i++) {
int k = h.get();
System.out.println("Getting : "+k);
try {
Thread.sleep(10);
} catch (InterruptedException ie) {
}
}
}
}
答案 0 :(得分:1)
我觉得你对控制台输出感到困惑。
重要的是,消费者中的每个.get()
都会获得生产者的所有元素。
当您删除所有令人困惑的System.out.
行并使用
class Consumer implements Runnable {
Holder h;
public Consumer(Holder h) {
this.h = h;
}
public void run() {
for (int i = 0; i < 1000; i++) {
int k = h.get();
if (k != i)
System.out.println("Got wrong value " + k + "expected value " + i);
}
}
}
您将看到您的代码正常运行。
我认为你的混淆来自看似这样的输出
Getting : 990
Putting : 993
Getting : 991
Getting : 992
The thread Consumer Going ta sleep...
Getting : 993
但是你也看到所有的get
都是正确的顺序,所有的put
也是如此。
因此,当涉及多个线程时,这是输出在Java中的工作方式的问题。
答案 1 :(得分:0)
一个线程将读取数据&amp;迭代可能需要的时间超过获取数据的次数。 由于所有线程同时访问数据和处理它超过预期的次数,应该有Thread.sleep一定的毫秒。
我遇到了同样的问题,在增加thread.sleep()后,它会读取一次&amp;处理一次