使用专用线程发送消息
我们现在有了传入消息的列表,现在我们可以在消息传入时对其进行处理。这可以通过创建一个阻塞的任务来完成messageQueue.take() https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html#take()。以下是此方法的快速实现:
public class MessageProcessor extends BukkitRunnable {
private BlockingQueue<Pair<WebSocket,String>> messageQueue;
public MessageProcessor (BlockingQueue<Pair<WebSocket,String>> messageQueue) {
this.messageQueue = messageQueue;
}
@Override
public void run() {
try {
Pair<WebSocket,String> next;
while(true) {
next = messageQueue.take();
if(next.getFirst() == null) {
// Special condition, will be explained later
return; // Quit run method
}
// System.out.println("Send message to " + next.getFirst()); // DEBUG
next.getFirst().send(next.getSecond());
}
} catch(InterruptedException e) {
Thread.currentThread().interrupt();
// Someone wanted to quit our thread, so we are quiting
} finally {
messageQueue.clear();
}
}
}
上述类别有2个特殊条件,next.getFirst() == null
and catch(InterruptedException e)
,当我们禁用插件退出任务时将使用这些。
我们需要在 bukkit 和我们的 Websocket 服务器启动时启动我们的任务,这样它就可以开始处理消息和发送数据。这在我们的onEnable()
使用以下代码:
新的 MessageProcessor (messageQueue).runTaskAsynchronously(this);
当我们的插件被禁用时,我们需要确保专用任务停止,以防止 bukkit 发送垃圾邮件“This plugin is not properly shutting down its async tasks when it is being reloaded.
”。这确实很容易做到,因为我们在上面为此制定了特殊条件。
为此,我们将以下代码放入我们的onDisable()
:
messageQueue.add(new Pair<>(null,null)); https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html#add(E)
该过程的最后一步是重写sendToAll
使用我们的队列的方法。这真的很容易做到,只需要我们更换 1 行即可。
public void sendToAll(String data) {
Collection<WebSocket> con = connections();
synchronized (con) {
for (WebSocket c : con) {
messageQueue.add(new Pair<>(c,data)); // Ferrybig: Use messageQueue
}
}
}
也可以进行相同的小修改sendData
方法,但不是我作为读者的练习而完成的。