Java 生产者消费者多线程为什么需要Thread.sleep?

Java 生产者消费者多线程为什么需要Thread.sleep?,java,multithreading,sleep,producer-consumer,Java,Multithreading,Sleep,Producer Consumer,虽然我确实了解线程间通信的要点,以及监视器上使用wait和notify来确保Put/Get操作同步,但我试图理解,当我们有一个工作的wait/notify机制时,为什么我们需要下面代码中的thread.sleep()?如果我删除thread.sleep()-输出将见鬼去 import java.io.*; import java.util.*; public class Test { public static void main(String argv[]) throws Throw

虽然我确实了解线程间通信的要点,以及监视器上使用wait和notify来确保Put/Get操作同步,但我试图理解,当我们有一个工作的wait/notify机制时,为什么我们需要下面代码中的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) {
            }
        }
    }
}
import java.io.*;
导入java.util.*;
公开课考试{
公共静态void main(字符串argv[])抛出可丢弃{
保持架h=新保持架();
螺纹p=新螺纹(新生产者(h),“生产者”);
螺纹c=新螺纹(新耗电元件(h),“耗电元件”);
p、 start();
c、 start();
}
}
阶级持有者{
INTA;
易变布尔hasPut;
公共同步作废put(int i){
while(hasPut){
试一试{
System.out.println(“线程”+thread.currentThread().getName()+“进入ta睡眠…”);
等待(1000);
}捕获(例外e){
e、 printStackTrace();
}
}
a=i;
hasPut=true;
notifyAll();
}
公共同步int get(){
而(!hasPut){
试一试{
System.out.println(“线程”+thread.currentThread().getName()+“进入ta睡眠…”);
等待(1000);
}捕获(例外e){
e、 printStackTrace();
}
}
hasPut=false;
notifyAll();
归还这个;
}
}
类生成器实现了Runnable{
持有人h;
公共制片人(持有人h){
这个,h=h;
}
公开募捐{
对于(int i=0;i<1000;i++){
System.out.println(“put:+i”);
h、 付诸表决(i);
试一试{
睡眠(10);
}捕获(中断异常ie){
}
}
}
}
类使用者实现Runnable{
持有人h;
公共消费者(持有人h){
这个,h=h;
}
公开募捐{
对于(int i=0;i<1000;i++){
int k=h.get();
System.out.println(“get:+k”);
试一试{
睡眠(10);
}捕获(中断异常ie){
}
}
}
}

我想你会被控制台的输出弄糊涂

重要的一点是,如果使用者中的每个
.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); 
        }
    }
}
但是您也可以看到所有的
get
s顺序正确,所有的
put
s顺序也正确。
因此,当涉及多个线程时,这是Java中输出工作方式的问题。

一个线程将读取数据&迭代可能需要的时间超过获取数据的次数。 由于所有线程并发访问数据并处理数据的次数超过预期,因此在某些毫秒内应该存在Thread.sleep


我也面临同样的问题,在增加thread.sleep()后,它只读取一次并处理一次

当您删除
thread.sleep()时,您看到了什么问题?我尝试了两次调用
Thread.sleep(10)
和不调用
的代码,但两种方法都没有发现问题。这是一个演示程序,向您展示了当一个踏板等待另一个踏板时会发生什么,这就是.sleep语句或到位的原因。将运行代码与它们进行比较,您不会看到不同的结果。多次运行它们,您将看到结果根据胎面交互而变化。运行时可以运行其他程序,也可以不运行其他程序。@Bron-当我从一个响应程序中删除睡眠时,GET/PUT的顺序完全是偶然的-控制台输出似乎很混乱-我猜保持wait/notify的工作状态我原以为P/G/P/G/P/G输出在没有睡眠的情况下会得到遵守()因为我们正在精确地控制这两个操作-但是因为我只删除了Sleep(),所以我的新手觉得Sleep()可能扮演了一个必要的角色…因为有了它-P/G/P/G。。。。序列很精确!我不明白为什么这个问题的由来是这样的谢谢拉斐尔-你完全正确-觉得这只是与控制台输出的细微差别有关很愚蠢-但是Put-Get似乎很荣幸,尽管它没有正确打印出来!谢谢大家!@用户2796381是的,我也有过同样的问题。这是我们都必须学习的一课。
Getting : 990
Putting : 993
Getting : 991
Getting : 992
The thread Consumer Going ta sleep...
Getting : 993