使用 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.
公平策略与读取队列的顺序有关。 producer/consumer 的执行顺序是消费者 take(),释放生产者(在 put() 上阻塞)。如果消费顺序重要,设置fairness=true
如果你想让线程保持活动状态,有一个在中断时表现良好的循环条件(见下文)。假设您想在 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
我在调试 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.
公平策略与读取队列的顺序有关。 producer/consumer 的执行顺序是消费者 take(),释放生产者(在 put() 上阻塞)。如果消费顺序重要,设置fairness=true
如果你想让线程保持活动状态,有一个在中断时表现良好的循环条件(见下文)。假设您想在 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