我正在尝试处理从MQ基础架构获得的一些消息。我有两个阻塞队列sharedQueue
和pubQueue
。 sharedqueue
充满了我从MQ基础架构获得的消息,如下所示。它将消息发送到sharedQueue
。
client.setCallback(new CallBack(“inst”,sharedQueue));
messagemanipulator线程将从sharedQueue
读取,处理它并将响应放到pubQueue
以供稍后发布。
new MessageManipulatorThread(sharedQueue,pubQueue).run();
发布者线程将从pubQueue
接收消息并将其发布到MQ基础结构。
new PublisherThread(pubQueue).run();
以下是完整代码:
public class ArrayBlockingQueueExample {
private BlockingQueue<String> sharedQueue = new ArrayBlockingQueue<>(64);
private BlockingQueue<String> pubQueue = new ArrayBlockingQueue<>(64);
public static void main(String[] args) throws MqttException, Exception {
new ArrayBlockingQueueExample().startThreads();
}
public void startThreads() throws MqttException, Exception{
MqttClient client = new MQTTClientFactory().getInstance();
client.setCallback(new CallBack("inst", sharedQueue));
new MessageManipulatorThread(sharedQueue,pubQueue).run();
new PublisherThread(pubQueue).run();
}
public MessageManipulatorThread( BlockingQueue<String> sharedQueue , BlockingQueue<String> pubQueue){
this.sharedQueue = sharedQueue;
this.pubQueue = pubQueue;
}
public void run() {
while (true) {
try {
String msg = sharedQueue.take();
System.out.println(Thread.currentThread().getName() + "manipulator runnning => "+msg);
pubQueue.put(msg);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class PublisherThread implements Runnable {
private BlockingQueue<String> sharedQueue;
public PublisherThread(BlockingQueue<String> sharedQueue){
this.sharedQueue = sharedQueue;
}
public void run() {
while (true) {
System.out.println("Running pub");
try {
System.out.println("pub=>"+sharedQueue.take() );
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
问题是new PublisherThread(pubQueue).run();
永远不会有效。我猜这是一个线程同步问题。pubQueue
应该等到MessageManipulatorThread
填充任何数据,但是它看起来不像那样。PublisherThread
正在等待pubQueue
获得自由,但它永远不会自由! ,还有什么我应该做的吗?非常感谢任何帮助。
答案 0 :(得分:6)
您正在使用Runnable.run()
代替Thread.start()
,所以:
new MessageManipulatorThread(sharedQueue,pubQueue).run();
new PublisherThread(pubQueue).run();
赢了工作。这是因为run()
实际上在当前线程中运行runnable的方法,而不是创建一个新线程并单独执行它。
相反,这样做:
new Thread(new MessageManipulatorThread(sharedQueue,pubQueue), "MessageManipulatorThread").start();
new Thread(new PublisherThread(pubQueue), "PublisherThread").start();
修改强>
fge在问题中发表了以下评论:
为什么不使用
ExecutorService
而不是手工完成工作?
为了澄清他的意思,他的意思是使用ExecutorService
来处理pubQueue
的消息,而不是创建一个线程来拉取消息并手动处理它们。该代码看起来像这样:
ExecutorService executor = Executors.newSingleThreadExecutor();
new Thread(new MessageManipulatorThread(sharedQueue, executor), "MessageManipulatorThread").start();
然后MessageManipulatorThread
类将更改为:
public class MessageManipulatorThread implements Runnable {
private BlockingQueue<String> sharedQueue;
private ExecutorService executor;
public MessageManipulatorThread(BlockingQueue<String> sharedQueue, ExecutorService executor){
this.sharedQueue = sharedQueue;
this.executor = executor;
}
public void run() {
while (true) {
try {
String msg = sharedQueue.take();
System.out.println(Thread.currentThread().getName() + "manipulator runnning => "+msg);
executor.execute(new PublisherThread(msg));
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
然后您更改PublisherThread
,以便它仅使用进程传递给它的单个消息。这是您尝试做的另一种方法。
这种方法也允许一些灵活性。使用另一种方法,PublisherThread
一次只能处理一条消息(同步)。使用ExecutorService
接口允许您更改实现,这可以允许它一次处理多个消息(异步),只需更改它:
ExecutorService executor = Executors.newSingleThreadExecutor();
对此:
ExecutorService executor = Executors.newFixedThreadPool(10);
该语句允许执行程序启动最多10个线程,这意味着一次最多可以处理10个消息。有关创建ExecutorService
实施的更多方法,请参阅Executors
课程。
答案 1 :(得分:1)
这两行是你的问题:
new MessageManipulatorThread(sharedQueue,pubQueue).run();
new PublisherThread(pubQueue).run();
首先应该让您的“线程”类扩展Thread
而不是仅仅实现Runnable
,然后再调用它:
new MessageManipulatorThread(sharedQueue,pubQueue).start();
new PublisherThread(pubQueue).start();
如上所述,您的代码实际上并不会生成任何新线程,因此第一个run()
方法永远不会返回,并且您的第二个run()
方法永远不会被调用。