我在调试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顺序争用访问;否则订单未指定。
答案 0 :(得分:1)
公平政策与读取队列的顺序有关。生产者/消费者的执行顺序是消费者使用take(),释放生产者(在put()上阻塞)。如果消费顺序很重要,则设置公平=真。
如果要保持线程处于活动状态,请设置一个在中断时表现良好的循环条件(参见下文)。大概你想在生产者中放一个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消耗事件:消费者四个