微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

生产者和消费者没有按顺序打印答案

如何解决生产者和消费者没有按顺序打印答案

我正在尝试编写应该按以下顺序打印输出的生产者和消费者

consumer 1
produce 1
consumer 2
produce 2

但它没有按顺序给出输出。为了在使用 synchronized 关键字时实现顺序,它甚至不打印任何输出

import java.util.concurrent.ArrayBlockingQueue;
import java.util.stream.IntStream;

 public class ProducerAndcosumer {


ArrayBlockingQueue<Integer> blockingQueue ;

public ProducerAndcosumer(int capacity) {
    this.blockingQueue = new ArrayBlockingQueue<Integer>(capacity);
}


public synchronized void consume(int data) {
    System.out.println(" consumer " + data);
    blockingQueue.offer(data);
}
public synchronized int produce() throws InterruptedException {
    int data = blockingQueue.take();
    System.out.println(" produce " + data);
    return data;
}

public static void main(String[] args) throws InterruptedException {
    
    ProducerAndcosumer pc = new ProducerAndcosumer(10);
    
    
    Runnable run1 = new Runnable() {
        @Override
        public void run() {
            System.out.println(" Entered consumer runner ");
            IntStream.range(1,20).forEach(pc::consume);
        }
    };
     new Thread(run1).start();
     
     Runnable run2 = new Runnable() {
         
         @Override
         public void run() {
             System.out.println(" Entered producer runner ");
             try {
                 for (int i = 0 ; i < 30 ; i++) {
                     pc.produce();
                 }
            } catch (InterruptedException e) {
                e.printstacktrace();
            }
         }
     };
     new Thread(run2).start();
  } 

}

请建议我如何解决它。还有一个问题,我们可以不用等待和通知来实现它。

解决方法

在您的代码中,您遇到了竞争条件问题。您应该提供对 ArrayBlockingQueue 的并发访问。许多可能的变体之一是下一个示例(带有两个信号量):

 public class ProducerAndConsumer {

    private final ArrayBlockingQueue<Integer> blockingQueue ;

    private final Semaphore semaphoreOne;

    private final Semaphore semaphoreTwo;

    public ProducerAndConsumer(int capacity) {
        this.blockingQueue = new ArrayBlockingQueue<>(capacity,true);
        this.semaphoreOne = new Semaphore(1);
        this.semaphoreTwo = new Semaphore(1);
    }


    public void consume(int data) throws InterruptedException {
        semaphoreOne.acquire();
        System.out.println(" consumer " + data);
        blockingQueue.offer(data);
        semaphoreTwo.release();
    }
    public void produce() throws InterruptedException {
        semaphoreTwo.acquire();
        int data = blockingQueue.take();
        System.out.println(" produce " + data);
        semaphoreOne.release();
    }

    public static void main(String[] args) throws InterruptedException {
        ProducerAndConsumer pc = new ProducerAndConsumer(10);

        Runnable run1 = () -> {
            System.out.println(" Entered consumer runner ");
            for (int i = 1; i < 20; i++) {
                try {
                    pc.consume(i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        Runnable run2 = () -> {
            System.out.println(" Entered producer runner ");
            try {
                for (int i = 0 ; i < 30 ; i++) {
                    pc.produce();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        new Thread(run1).start();
        new Thread(run2).start();
    }
}

这个程序的输出是:

 Entered consumer runner 
 Entered producer runner 
 consumer 1
 produce 1
 consumer 2
 produce 2
 consumer 3
 produce 3
 consumer 4
 produce 4
 consumer 5
 produce 5
 consumer 6
 produce 6
 consumer 7
 produce 7
 consumer 8
 produce 8
 consumer 9
 produce 9
 consumer 10
 produce 10
 consumer 11
 produce 11
 consumer 12
 produce 12
 consumer 13
 produce 13
 consumer 14
 produce 14
 consumer 15
 produce 15
 consumer 16
 produce 16
 consumer 17
 produce 17
 consumer 18
 produce 18
 consumer 19
 produce 19

此外,当您声明两个方法 consume produce synchronized 时,您将遇到死锁,因为这两个方法都将尝试通过一个监视器进行同步(对象 ProducerAndConsumer),见线程转储 enter image description here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。