import java.io.BufferedReader;
import java.io.InputStreamReader;public class ThreadTest {
    
    public static void main(String[] args) {
        StudentInfo stu = new StudentInfo();
        Thread t1 = new Thread(new Producer(stu));
        Thread t2 = new Thread(new Customer(stu));
        Thread t3 = new Thread(new Customer(stu));
        t1.start();
        t2.start();
        
        t3.start();  // 如果这个线程不启动,就能正常运行
                      // 一旦启动,运行一段时间就会出错了
    }
}class StudentInfo {
    String name = "";
    boolean bFull = false;
    public synchronized void pushData(String name) {
        //如果有数据,那么该线程等待,至到消费者线程取完数据以后才被唤醒
        while (bFull) {
            try {
                this.wait();
            } catch(Exception ex){
                System.out.println(ex.toString());
            };
        }
        this.name = name;
        bFull = true;
        System.out.println("生产者线程:"+this.name);
        this.notify();
    }
    public synchronized String popData() {
        //如果没有数据,那么该线程等待,至到生产者线程放入数据以后才被唤醒
        while (!bFull) {
            try {
                this.wait();
            } catch(Exception ex){
                System.out.println(ex.toString());
            };
        }
        bFull = false;
        System.out.println("消费者线程:"+this.name);
        this.notify();
        return this.name;
    }
}class Producer implements Runnable {
    StudentInfo stu;
    public Producer(StudentInfo stu) {
        this.stu = stu;
    }
    static int i=1;
    public void run() {
        while(true){
            // 生产者如何停下来?
            // 比如这里的数据是从数据库里面取,当已经取完的时候,
            // 如何停下来,并通知消费者?
            // if(没有数据){停止生产,通知消费者}
            stu.pushData("Name " + i);
        }
    }
}class Customer implements Runnable {
    StudentInfo stu;
    public Customer(StudentInfo stu) {
        this.stu = stu;
    }
    public void run() {
        while(true){
            // 如果生产者已经停止生产了,
            // 如何结束程序?
            stu.popData();
        }
    }
};

解决方案 »

  1.   

    上面是我改了CSDN上一个朋友给的代码
    我有几个问题不明白1.如何能有多个消费者?
    2.生产者如果停止生产,如何让消费者处理完所有已经生产的产品之后退出程序?谢谢大家,非常感谢
      

  2.   

    1.建一个队列,用于保存消费者
    2.在处理StudentInfo时调用线程时,判断队列是否所有的产品的处理完,合则退出
      

  3.   

    看看这段代码吧:
    //多个生产者,多个消费者的例子
    import java.util.*;
    public class ThreadTest
    {
    public static void main(String [] args)
    {
    MyStack st = new MyStack();
    Thread t1 = new Thread(new Producer(st));
    Thread t2 = new Thread(new Producer(st));
    Thread t3 = new Thread(new Customer(st));
    Thread t4 = new Thread(new Customer(st));
    t1.start();
    t2.start();
    t3.start();
    t4.start();
    }
    }
    class MyStack
    {
    //使用Vector类创建一个栈,它有无限大的空间。所以我只考虑栈为空的情况
    private Vector buffer = new Vector(400,200);
    public synchronized void push(char c,int num) 
    {
    Character charObj = new Character(c);
    buffer.addElement(charObj);
    System.out.println("Producer" + num + ": " + c);
    this.notify();
    }
    public synchronized char pop(int num) 
    {
    char c;
    while (buffer.size() == 0)
    {
    try {this.wait();} catch (InterruptedException e) {}
    }
    c = ((Character)buffer.remove(buffer.size()-1)).charValue();
    System.out.println(" Customer" + num + ": " + c);
    return c; }};
    class Producer implements Runnable
    {
    MyStack st;
    private static int counter = 1;
    private int num;
    public Producer(MyStack st)
    {
    this.st = st;
    this.num=counter++;
    }
    public void run()
    {
    char c;
    for (int i = 0; i < 200; i++) 
    {
    c = (char)(Math.random() * 26 + 'A');
    st.push(c,num);
    try 
    {
    Thread.sleep((int)(Math.random() * 300));
    } catch (InterruptedException e) 
    {
    }
    } }
    }
    class Customer implements Runnable
    {
    MyStack st;
    private static int counter = 1;
    private int num;
    public Customer(MyStack st)
    {
    this.st = st;
    num = counter++;
    }
    public void run()
    {
    char c;
    for (int i = 0; i < 200; i++) 
    {
    c = st.pop(num);
    try 
    {
    Thread.sleep((int)(Math.random() * 300));
    }
    catch (InterruptedException e) 
    {
    }
    } }
    };
      

  4.   

    单个生产者
    多个消费者您原先的那个代码就可以
    把notify改成notifyAll就可以了不过我现在不知道如何让这个程序停下来
    因为消费者是无法知道生产者要生产多少个产品……
      

  5.   

    把notify改成notifyAll 看起来是可以了,
    但是生产的一个东西有好几个人抢,不合适。
    我上边的例子你可以参考一下。
      

  6.   

    非常感谢您的帮助;您给的第二个多生产者,多消费者的例子中,
    buffer就是缓冲池;如果缓冲池的大小有限制,
    那么生产者和消费者之间又要互相限制,push该如何改写?因为push中,如果它wait了,就应该由消费者来唤醒它吧
    我逻辑上能想明白,但是程序里面却不知道如何表达这种限制关系那么push和pop如何改写?请指点迷津,谢谢
      

  7.   

    我把pop和push都改成如下的结构了
    不知道会不会有潜在的危险? Character charObj = new Character(c);
                    while(buffer.size()==3)
                    {
                        System.out.println("缓冲池满");
                        try {this.wait();} catch (InterruptedException e) {}
                    }
    buffer.addElement(charObj);
    System.out.println("Producer" + num + ": " + c);
    this.notify();
      

  8.   

    //多个生产者,多个消费者的例子
    //多个生产者生产完以后,停止生产,消费者开始消费,直到消费完毕。
    //Writed by ysy 2005-11-19 16:41:00
    import java.util.*;
    import java.io.*;
    public class ThreadTest
    {
    public static void main(String [] args)
    {
    int i=0;
    try
    {
    System.out.println("请输入生产的数量:");
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    i = Integer.parseInt(br.readLine());
    }
    catch (IOException ex)

    System.out.println(ex.getMessage());

    MyStack st = new MyStack(i);
    Thread t1 = new Thread(new Producer(st));
    Thread t2 = new Thread(new Producer(st));
    Thread t3 = new Thread(new Customer(st));
    Thread t4 = new Thread(new Customer(st));
    t1.start();
    t2.start();
    t3.start();
    t4.start();
    }
    }
    class MyStack
    {
    //使用Vector类创建一个栈,它有无限大的空间。所以我只考虑栈为空的情况
    public MyStack(int initialCapacity)
    {
    this.initialCapacity = initialCapacity;
    }
    private int initialCapacity=0;
    private Vector buffer = new Vector(initialCapacity);
    boolean bFull = false; //判断空间是否为满
    boolean bCustomer = false;  //中止消费者的标志
    public synchronized void push(char c,int num) 
    {
    Character charObj = new Character(c);
    buffer.addElement(charObj);
    System.out.println("Producer" + num + ": " + c);
    if (buffer.size()  == initialCapacity)
    {
    System.out.println("生产完毕,开始消费");
    bFull = true;
    this.notifyAll();
    }
    }
    public synchronized char pop(int num) 
    {
    char c;
    if (buffer.size() == 0 || !bFull )
    {
    try {this.wait();} catch (InterruptedException e) {}
    }
    c = ((Character)buffer.remove(buffer.size()-1)).charValue();
    System.out.println(" Customer" + num + ": " + c);
    if (buffer.size() == 0  )
    {
    System.out.println("消费结束。");
    bCustomer = true;
    }

    return c; }
    };
    //生产者
    class Producer implements Runnable
    {
    MyStack st;
    private static int counter = 1;
    private int num;
    public Producer(MyStack st)
    {
    this.st = st;
    this.num=counter++;
    }
    public void run()
    {
    char c;
    while (!st.bFull)
    {
    c = (char)(Math.random() * 26 + 'A');
    st.push(c,num);
    try 
    {
    Thread.sleep((int)(Math.random() * 300));
    } catch (InterruptedException e) 
    {
    }
    } }
    }
    //消费者
    class Customer implements Runnable
    {
    MyStack st;
    private static int counter = 1;
    private int num;
    public Customer(MyStack st)
    {
    this.st = st;
    num = counter++;
    }
    public void run()
    {
    char c;
    while (!st.bCustomer)
    {
    c = st.pop(num);
    try 
    {
    Thread.sleep((int)(Math.random() * 300));
    }
    catch (InterruptedException e) 
    {
    }
    } }
    };