我正在创建多个线程,我希望每个线程在其BlockingQueue中侦听任何新消息2秒钟,然后消失。我正在使用以下代码:
public class Main {
public static void main(String[] argv) throws Exception {
int capacity = 10;
BlockingQueue<String> queue = new ArrayBlockingQueue<String>(capacity);
ArrayList<String> names = new ArrayList<String>();
names.add("Apple"); names.add("Banana"); names.add("Mango");
HashMap<String, Worker> workermap = new HashMap<String, Worker>();
for (String name: names) {
Worker a_worker = new Worker(queue);
a_worker.setName(name);
a_worker.start();
workermap.put(name, new Worker(queue));
}
queue.put("Hello ");
}
}
class Worker extends Thread {
BlockingQueue<String> q;
Worker(BlockingQueue<String> q) {
this.q = q;
}
public void run() {
try {
long start = System.currentTimeMillis();
long end = start + 2*1000;
while (true) {
String x = q.take();
if(System.currentTimeMillis()>=end){
System.out.println("No new message since two seconds, killing thread " + this.getName());
Thread.interrupted();
// break;
}
// if (x == null) {
// break;
// }
System.out.println(x + "from " + this.getName());
}
} catch (InterruptedException e) {
}
}
}
我希望输出如下:
Hello from Apple
Hello from Banana
Hello from Mango
No new message since two seconds, killing thread Apple
No new message since two seconds, killing thread Banana
No new message since two seconds, killing thread Mango
但是我只得到Hello from Apple
,然后什么也没有。该过程继续进行,没有任何进一步的输出。除了使用计时器杀死线程之外,我还尝试检查queue元素是否为null,但没有成功。我要去哪里错了?
答案 0 :(得分:1)
如上所述,您需要使用pool而不是take(),也不能使用Thread.interrupted();
来interrupt
到thread
。您需要使用Thread.currentThread().interrupt();
。另外,您无需检查时间,因为BlockingQueue#poll
会等待2
秒。
while (!Thread.currentThread().isInterrupted()) {
String x = q.poll(2, TimeUnit.SECONDS);
if (x == null)
System.out.println("No new message since two seconds, killing thread " + this.getName());
Thread.currentThread().interrupt();
System.out.println(x + "from " + this.getName());
}
输出:
No new message since two seconds, killing thread Mango
Hello from Mango
No new message since two seconds, killing thread Apple
nullfrom Apple
No new message since two seconds, killing thread Banana
nullfrom Banana
编辑:但是我相信您根本不需要循环。只需下面的代码即可为您工作。
public void run() {
try {
String x = q.poll(2, TimeUnit.SECONDS);
if (x == null)
System.out.println("No new message since two seconds, killing thread " + this.getName());
System.out.println(x + "from " + this.getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
答案 1 :(得分:1)
我只是尝试对您的代码进行最小程度的修复:
import java.util.ArrayList;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class Main {
public static void main(String[] argv) throws Exception {
int capacity = 10;
BlockingQueue<String> queue = new ArrayBlockingQueue<String>(capacity);
ArrayList<String> names = new ArrayList<String>();
names.add("Apple"); names.add("Banana"); names.add("Mango");
for (String name: names) {
Worker a_worker = new Worker(queue);
a_worker.setName(name);
a_worker.start();
}
queue.put("Hello");
queue.put("Bonjour");
}
}
class Worker extends Thread {
BlockingQueue<String> q;
Worker(BlockingQueue<String> q) {
this.q = q;
}
public void run() {
long start = System.currentTimeMillis();
long end = start + 2; //just wait for two milliseconds
while (true) {
String x = q.poll();
if(x != null) {
System.out.println(x + " from " + this.getName());
} else if(System.currentTimeMillis() >= end){
System.out.println("No new message since two milliseconds, killing thread " + this.getName());
interrupt();
}
if(interrupted()) {
break;
}
}
}
}
样本输出:
Hello from Apple
No new message since two milliseconds, killing thread Banana
Bonjour from Mango
No new message since two milliseconds, killing thread Apple
No new message since two milliseconds, killing thread Mango