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

时间:2013-09-19 16:58:32

标签: java multithreading sleep producer-consumer

虽然我理解了线程间通信的要点以及监视器上等待和通知的使用,以确保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) {
            }
        }
    }
}

2 个答案:

答案 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;处理一次