在Java中使用wait()和notify()进行阻止

Anu*_*rag 3 java multithreading synchronized producer-consumer

我使用的消费者代码编写和制作wait(),并notify()在Java中.创建并调用Thread-0并创建produce()Thread-1并调用它consume().

public class Processor {

  private volatile List<Integer> list = new ArrayList<>();
  private final int MAX_CAPACITY = 5;
  Object lock = new Object();

  public void produce() throws InterruptedException {

    while (true) {

      while (list.size() == MAX_CAPACITY) {
        System.out.println("List is full! Producer is Waiting....");
        synchronized (lock) {
          lock.wait();
        }
      }

      synchronized (lock) {
        int random = new Random().nextInt(100);
        list.add(random);
        System.out.println("Added to list:" + random);
        lock.notify();
      }
    }
  }

  public void consume() throws InterruptedException {

    while (true) {

      while (list.size() == 0) {
        System.out.println("List is empty!! Consumer is Waiting...");
        synchronized (lock) {
          lock.wait();
        }
      }

      synchronized (lock) {
        int i = list.remove(0);
        System.out.println("Removed from list:" + i);
        lock.notify();
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

问题是在执行期间,程序在以下情况后停止produce():

List is empty!! Consumer is Waiting...
Added to list:22
Added to list:45
Added to list:72
Added to list:91
Added to list:51
List is full! Producer is Waiting....
Run Code Online (Sandbox Code Playgroud)

我无法理解这里的问题是什么.我以某种方式想出从块中while循环包装代码并解决问题.synchronizedproduce()consume()

produce()

synchronized (lock) {
                while (list.size() == MAX_CAPACITY) {
                    System.out.println("List is full! Producer is Waiting....");

                    lock.wait();
                }
Run Code Online (Sandbox Code Playgroud)

consume

synchronized (lock) {
                while (list.size() == 0) {
                    System.out.println("List is empty!! Consumer is Waiting...");

                    lock.wait();
                }
            }
Run Code Online (Sandbox Code Playgroud)

这是什么问题?这是线程饥饿还是死锁的情况?

编辑:调用类:

public class App {
    public static void main(String[] args) {
        final Processor processor = new Processor();

        Runnable r1 = new Runnable() {

            @Override
            public void run() {
                try {
                    processor.produce();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        };

        Runnable r2 = new Runnable() {

            @Override
            public void run() {
                try {
                    processor.consume();
                } catch (InterruptedException e) {

                    e.printStackTrace();
                }
            }
        };

        Thread t1 = new Thread(r1);
        Thread t2 = new Thread(r2);

        t1.start();
        t2.start();


    }
}
Run Code Online (Sandbox Code Playgroud)

Pet*_*rey 6

当你执行list.size()它不是线程安全的,没有保证你将看到另一个线程中的值更改.如果JIT检测到您没有在该线程中更改它,则它甚至可以内联该值.

通过将synchronized块放在循环外部,可以确保值的变化是可见的(因为它也在while(true)循环内部).

  • 你不应该让生产者和消费者在同一件事上等待.实际上,使用不同的同步构造可能更好地实现了这一点; 例如队列/队列 (3认同)