语言:Java
我有一个固定的线程池运行,所有人都必须在某个时刻提出问题并以(是/否)的形式接受用户输入,这基本上决定了它的进一步执行。由于我不想混合来自多个线程的输出问题,因此将有另一个任务/线程以固定速率运行(单个)(进一步称为主线程),可用于获取问题并显示它给用户。线程提出的问题数量可能会有所不同,一旦问题得到回复,就不再需要它了。
此时我的当前实现使用LinkedTransferQueue
,它基本上允许我在主线程和问题线程之间共享数据,而不必等待轮询。
我创建了ArrayList
类的同步Task
,每个类都包含LinkedTransferQueue<String>
。该线程创建一个新的Task
,并使用transfer()
方法将其问题添加到其队列中。主线程将它们拾取并从用户获得响应,并将其放回到同一队列中。这里的优点是LinkedTransferQueue
提供了take()
方法,允许我在没有轮询的情况下等待。
其他方法包括使用volatile shared
变量,其值由主线程更新,并且不断被另一个线程轮询。
请建议是否有任何其他数据结构可用于此类用例。根据我的理解,这不完全是生产者 - 消费者的问题。如果您有任何其他问题,请发布问题。
谢谢!
答案 0 :(得分:0)
由于您希望线程等待答案,我建议您创建一个包含问题文本的问题对象,可以存储答案,并在答案可用时设置CountDownLatch
进行跟踪。< / p>
public final class Question {
private final String question;
private String answer;
private CountDownLatch latch = new CountDownLatch(1);
public Question(String question) {
this.question = question;
}
public String getQuestion() {
return this.question;
}
public String getAnswer() throws InterruptedException {
this.latch.await();
return this.answer;
}
public void setAnswer(String answer) {
this.answer = answer;
this.latch.countDown();
}
}
然后,您的工作线程可以将该问题发送到主Queue
,并等待答案,例如
public final class Worker implements Runnable {
private final Queue<Question> queue;
private final int delayInSeconds;
private final String[] questions;
public Worker(Queue<Question> queue, int delayInSeconds, String... questions) {
this.queue = queue;
this.delayInSeconds = delayInSeconds;
this.questions = questions;
}
@Override
public void run() {
List<String> answers = new ArrayList<>();
try {
for (String question : this.questions) {
Thread.sleep(this.delayInSeconds * 1000L);
Question q = new Question(question);
this.queue.add(q);
String answer = q.getAnswer();
answers.add(answer);
}
} catch (InterruptedException unused) {
System.out.println("Interrupted");
}
System.out.println(answers);
}
}
主线程然后会使用某种BlockingQueue
来等待问题,并一次处理一个问题,例如像这样:
public static void main(String[] args) throws Exception {
BlockingQueue<Question> queue = new LinkedBlockingQueue<>();
Worker w1 = new Worker(queue, 3, "Can you play poker?",
"Can you juggle?",
"Can you summersault?");
Worker w2 = new Worker(queue, 4, "How old are you?",
"How tall are you?");
new Thread(w1).start();
new Thread(w2).start();
Scanner in = new Scanner(System.in);
for (int i = 0; i < 5; i++) {
Question q = queue.take();
System.out.println(q.getQuestion());
String answer = in.nextLine();
q.setAnswer(answer);
}
}
示例输出
Can you play poker?
yes
How old are you?
13
Can you juggle?
no
How tall are you?
5 11
Can you summersault?
[13, 5 11]
no
[yes, no, no]