Java多线程等待并通知

时间:2015-12-09 19:07:23

标签: java multithreading

我正在刷新我对Java的知识,并尝试编写一个Wait and Notify(Producer,Consumer)类型的多线程程序。 想法是两个有一个生产者线程,它将数据添加到数组列表,并通知正在等待生产者线程获得的锁的消费者线程。 代码提供的输出不是预期的输出。

enter image description here

但我期望看到的是

enter image description here

如果您看到两个消费者线程都处于等待状态。当第一个生成器线程将数据添加到arraylist中时,它会向所有等待的线程发送notifyall信号。我将Producer线程停放了10秒,以便等待线程有时间选择数组列表并显示数组的内容。此时,数组的大小应为1.

package Threads_New;

import java.util.ArrayList;
import java.util.List;

public class Producer_Consumer2 {

    List<String> sharedList = new ArrayList();
    int count = 0;
    Object o = new Object();

    public void producer()

    {

        synchronized (o) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()
                    + "-Adding a value-" + count);
            count++;
            sharedList.add("Apple-" + count);
            o.notifyAll();
            System.out.println("The Waiting thread is notified");
            try {
                Thread.sleep(10000);
            } catch (Exception ex) {
                ex.printStackTrace();
            }

        }

    }

    public void consumer() {

        System.out.println(Thread.currentThread().getName()
                + "- came inside consumer");
        synchronized (o) {
            try {
                o.wait();
                System.out.println(Thread.currentThread().getName()
                        + "- Notification recieved");
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
            System.out.println("I was waiting and now got notified");
            for (String s : sharedList) {
                System.out.println("Data from the sharedList is:" + s);
            }

        }
    }

    public void ThreadStarter() {
        Thread[] T = new Thread[3];
        int run = 0;
        while (run < 2) {
            T[run] = new Thread(new Runnable() {

                @Override
                public void run() {
                    producer();
                }
            });

            T[run + 1] = new Thread(new Runnable() {

                @Override
                public void run() {
                    consumer();
                }
            });

            /*
             * for(int i=0;i<10;i++) { t1.start(); t2.start(); }
             */

            T[run].start();
            T[run + 1].start();
            run++;
        }

        /*
         * for(int i=0;i<21;i++) { try{ T[i].join(); T[i+1].join();
         * }catch(InterruptedException ex) { ex.printStackTrace(); } }
         */

    }

    public static void main(String[] args) {
        Producer_Consumer2 pc = new Producer_Consumer2();
        pc.ThreadStarter();
    }

}

3 个答案:

答案 0 :(得分:1)

据推测,你的制片人的睡眠是模拟一段时间,它不会产生任何东西,消费者应该在这段时间内取得进步。但它不能,因为生产者代码仍然在synchronized块内。您需要将sleep移到synchronized块之外。

此外,您的消费者会调用​​wait而不确定它尚未发生的事情。这是一个非常严重的错误,因为如果你等待已经发生的事情,你可能会永远等待。

答案 1 :(得分:0)

我认为至少你遇到的部分问题是生产者即使在睡觉时也持有锁定对象。您应该将synchronized(o)块放在您执行notifyAll的位置周围

答案 2 :(得分:0)

应该在循环内调用

wait()方法以检查满足条件,以便在继续之前等待的谓词为真,否则可能导致虚假唤醒。 wait()方法的Java doc链接:

http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#wait%28%29