有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java问题调试生产者消费者问题

我试图理解生产者和消费者的问题。为了复制这个问题,我编写了以下代码

package com.company;

import java.util.ArrayDeque;
import java.util.Queue;

public class ProducerConsumerProblem {

    private static Queue<Integer> q = new ArrayDeque<>(5);

    public static void main(String args[]) {

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

        Thread t = new Thread( p );
        Thread t1 = new Thread( c );

        t.start();
        t1.start();
    }

    public static class Producer implements Runnable {

        @Override
        public void run() {
            while(true) {
                if (q.size() == 5) {
                    continue;
                }
                System.out.println( "Adding to queue" );
                q.add( 1 );
            }
        }
    }
    public static class Consumer implements Runnable {

        @Override
        public void run() {
            while(true) {
                if (q.size() == 0) {
                    continue;
                }
                System.out.println( "Removing from queue" );
                q.remove();
            }
        }
    }
}

我本来希望得到类似concurrent exception的结果,但是当队列为空或队列已满时,代码就会停止。我的问题是,为什么当队列为空或已满时,代码会停止,因为我将使用者和生产者都放入了一个无限循环中,即使它们当前执行的是错误的读取,但在稍后的某个点上,它们将执行良好的读取,并且生产者或消费者都应该工作。请帮我解决这个问题


共 (1) 个答案

  1. # 1 楼答案

    这两个线程可能会看到不同的大小,因为您的代码不是线程安全的,您的add&;删除操作在不同的线程上完成

    当您在线程1上执行q.add( 1 );操作时,它不一定会在内存(即RAM)上写入更新的数组,它可能仍在CPU寄存器中,并且当这两个线程发生上下文切换时,您对第二个线程的更改也可能消失,并且看不到更新的大小。如果使用同步,当同步化块结束时,同步块中的所有更改都会保留到RAM中,这样就不会再发生不必要的行为

    因为ArrayDeque不是线程安全的,所以需要外部同步来确保代码的线程安全,或者使用并发数据结构