使用 SynchronousQueue 解决消费者生产者并发问题。公平 属性 无效

Solving consumer producer concurrency issue with SynchronousQueue. Fairness property not working

我在调试 SynchronousQueue 时遇到问题。它在 android 工作室,但它的 java 代码应该无关紧要。我将 true 传递给 SynchronousQueue 的构造函数,因此它的 "fair" 意味着它是一个 fifo 队列。但是不守规矩,还是让消费者先印,生产者后印。我遇到的第二个问题是我希望这些线程永不消亡,你认为我应该在生产者和消费者线程上使用 while 循环并让它们保持 "producing and consuming" 彼此吗?

这是我的简单代码:

   package com.example.android.floatingactionbuttonbasic;


import java.util.concurrent.SynchronousQueue;

import trikita.log.Log;


public class SynchronousQueueDemo {


    public SynchronousQueueDemo() {
    }


    public void startDemo() {
        final SynchronousQueue<String> queue = new SynchronousQueue<String>(true);

        Thread producer = new Thread("PRODUCER") {
            public void run() {
                String event = "FOUR";
                try {
                    queue.put(event); // thread will block here
                   Log.v("myapp","published event:", Thread
                           .currentThread().getName(), event);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        };

        producer.start(); // starting publisher thread

        Thread consumer = new Thread("CONSUMER") {
            public void run() {
                try {
                    String event = queue.take(); // thread will block here
                    Log.v("myapp","consumed event:", Thread
                            .currentThread().getName(), event);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        };

        consumer.start(); // starting consumer thread

    }

}

启动我简单调用的线程new SynchronousQueueDemo().startDemo();

无论我将什么传递给 synchronousQueue 构造函数,日志总是看起来像这样 "fair":

/SynchronousQueueDemo$override(26747): myapp  consumed event: CONSUMER    FOUR
V/SynchronousQueueDemo$override(26747): myapp published event:PRODUCER    FOUR

检查 docs here,它表示如下:

public SynchronousQueue(boolean fair) Creates a SynchronousQueue with the specified fairness policy. Parameters: fair - if true, waiting threads contend in FIFO order for access; otherwise the order is unspecified.

  1. 公平策略与读取队列的顺序有关。 producer/consumer 的执行顺序是消费者 take(),释放生产者(在 put() 上阻塞)。如果消费顺序重要,设置fairness=true

  2. 如果你想让线程保持活动状态,有一个在中断时表现良好的循环条件(见下文)。假设您想在 Producer 中放置一个 Thread.sleep(),以限制事件产生的速率。

    public void run() {
        boolean interrupted = false;
        while (!interrupted) {
            try {
                 // or sleep, then queue.put(event)
                 queue.take(event); 
            } catch (InterruptedException e) {
                interrupted = true;;
            }
        }
    }
    

SynchronousQueue 工作在一个简单的概念上。只有有消费者,你才能生产。

1) 现在,如果您在没有任何 queue.take() 的情况下开始执行 queue.put(),线程将在那里阻塞。所以只要你有 queue.take(),Producer 线程就会被解除阻塞。

2) 同样,如果您开始执行 queue.take(),它将阻塞直到有生产者。所以一旦你有 queue.put(),Consumer Thread 就会被阻塞。

所以queue.take()一执行,Producer线程和Consumer线程都畅通了。但是您确实意识到生产者和消费者都 运行 在不同的线程中。因此,您在阻塞调用之后放置的任何消息都可以执行。在我的例子中,输出的顺序是这样的。制作人先打印出来。

V/SynchronousQueueDemo$1$override(26747):myapp 已发布 event:PRODUCER 四 /SynchronousQueueDemo$2$override(26747): myapp consumed event: CONSUMER FOUR