使用SynchronousQueue解决消费者生产者并发问题。公平财产不起作用

时间:2016-01-30 04:21:24

标签: java android multithreading blockingqueue

我在调试SynchronousQueue时遇到问题。它在Android工作室,但不应该重要的Java代码。我正在传递给SynchronousQueue的构造函数,所以它的公平"意思是它的一个fifo队列。但是它不遵守规则,它仍然让消费者首先打印,然后让制片人打印出来。我的第二个问题是我希望这些线程永远不会消亡,你认为我应该在生产者和消费者线程上使用while循环,并让他们保持"生产和消费"彼此?

这是我的简单代码:

   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构造函数是什么&#34; fair&#34;

,日志总是看起来像这样
/SynchronousQueueDemo$2$override(26747): myapp  consumed event: CONSUMER    FOUR
V/SynchronousQueueDemo$1$override(26747): myapp published event:PRODUCER    FOUR

检查docs here,它说明如下:

  

public SynchronousQueue(boolean fair)   使用指定的公平策略创建SynchronousQueue。   参数:   公平 - 如果为真,则等待线程按FIFO顺序争用访问;否则订单未指定。

2 个答案:

答案 0 :(得分:1)

  1. 公平政策与读取队列的顺序有关。生产者/消费者的执行顺序是消费者使用take(),释放生产者(在put()上阻塞)。如果消费顺序很重要,则设置公平=真。

  2. 如果要保持线程处于活动状态,请设置一个在中断时表现良好的循环条件(参见下文)。大概你想在生产者中放一个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;;
            }
        }
    }
    

答案 1 :(得分:1)

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

1)现在,如果您开始执行queue.put()而没有任何queue.take(),则线程将在那里阻止。所以,只要你有queue.take(),生产者线程就会被解锁。

2)同样,如果你开始做queue.take(),它将会阻止,直到有一个制作人。所以一旦你有queue.put(),消费者线程就会被阻止。

因此,只要执行queue.take(),生产者和消费者线程就会被解除阻塞。但是你确实意识到Producer和Consumer都在单独的线程中运行。因此,可以执行阻塞调用之后放置的任何消息。在我的情况下,输出的顺序是这个。制作人先被打印出来。

V / SynchronousQueueDemo $ 1 $覆盖(26747):myapp发布的事件:PRODUCER FOUR / SynchronousQueueDemo $ 2 $覆盖(26747):myapp消耗事件:消费者四个