在多线程Java

时间:2016-03-29 07:15:41

标签: java multithreading synchronization thread-safety deadlock

我有一个代码,其中两个实现Runnable的线程类正在运行并共享一个Buffer类的公共对象。

虽然我已经在我的知识中正确使用了synchronized块和wait()notify()方法,但是当我在try / catch块中使用Thread.sleep(0)睡眠时,在一些接受的输出之后结果它陷入了僵局。

当我使用Thread.sleep(1000)的1000毫秒和使用Thread.sleep(3000)的{​​3000}的线程Bheem进行线程时,未检测到问题

这是线程中常见的生产者 - 消费者情景,我故意将消费者置于生产者之上。

P.S。 - 我已经从最后修改了输出。实际产量非常大。

以下代码位于Bheem类

public void consume() {

        while (ob.buffer >= 1) {
            synchronized (ob) {
                System.out.println(Thread.currentThread().getName()
                        + "    started eating Ladoos with currently "
                        + (ob.buffer--) + " ladoos in plate");

                try {
                    Thread.sleep(0); // bheem takes 1.5 sec to eat

                    ob.notify();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        synchronized (ob) {

            try {
                System.out
                        .println("Plate is empty, bheem will wait for ladoos to serve ");
                ob.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    public void run() {

        while (true) {

            consume();
        }
    }

这是Cook课程

public void produce() {

        while (ob.buffer < 5) {
            synchronized (ob) {

                System.out.println(Thread.currentThread().getName()
                        + "  started making Ladoos with currently "
                        + (ob.buffer++) + " ladoos in plate");

                try {
                    Thread.sleep(0); // 1 sec time taken to make a ladoo

                    ob.notify();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        synchronized (ob) {

            try {
                System.out.println("Plate is full, cook will wait ");
                ob.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    public void run() {

        while (true) {

            produce();
        }

    }

这是为了理解观众而调用的主要方法

public static void main(String[] args) {

        Buffer b = new Buffer(0);

        Producer p = new Producer(b);
        Consumer c = new Consumer(b);

        Thread producer = new Thread(p, "Cook");
        Thread consumer = new Thread(c, "Bheem");

        System.out.println("Main started");
        // buffer size is taken as 5 max.
        consumer.start(); // bheem takes 1.5 sec to finish a ladoo



        /*try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/


        producer.start(); // cook takes 1 sec to prepare ladoo

输出

Plate is empty, bheem will wait for ladoos to serve 
Cook  started making Ladoos with currently 0 ladoos in plate
Bheem    started eating Ladoos with currently 1 ladoos in plate
Plate is empty, bheem will wait for ladoos to serve 
Cook  started making Ladoos with currently 0 ladoos in plate
Bheem    started eating Ladoos with currently 1 ladoos in plate
Plate is empty, bheem will wait for ladoos to serve 
Cook  started making Ladoos with currently 0 ladoos in plate
Bheem    started eating Ladoos with currently 1 ladoos in plate
Plate is empty, bheem will wait for ladoos to serve 
Cook  started making Ladoos with currently 0 ladoos in plate
Bheem    started eating Ladoos with currently 1 ladoos in plate
Cook  started making Ladoos with currently 0 ladoos in plate
Cook  started making Ladoos with currently 1 ladoos in plate
Cook  started making Ladoos with currently 2 ladoos in plate
Cook  started making Ladoos with currently 3 ladoos in plate
Cook  started making Ladoos with currently 4 ladoos in plate
Plate is full, cook will wait 
Plate is empty, bheem will wait for ladoos to serve 

1 个答案:

答案 0 :(得分:0)

当消费者拿到最后一个ladoo时,是什么阻止你的制作人完全填满牌照并在之前调用最后的notify() 消费者设法拨打wait()?同样地,当盘子变满时,是什么阻止消费者在生产者进入notify()之前拿最后一个ladoo并调用最后一个wait()

如果某个其他线程没有等待接收通知,则对o.notify()的调用 nothing 。也就是说,对象o不记得它已被通知。