java - 循环功能在开始时冻结
问题描述
我正在为我的 Minecraft 服务器制作一个插件,它每 5 秒根据在线玩家的数量更新一个 API。每次服务器启动时,它都会在启用插件时卡住。
这是功能:
public static void playerListLoop(String status, int onlinePlayers) {
Boolean on = true;
try {
while (on = true) {
try {
URL url = new URL("http://192.168.1.14:3000");
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("x-_id", "518747784");
connection.setRequestProperty("x-api-key", "7");
connection.setDoOutput(true);
String urlParameters = "{\"survival\": {\"status\": \"" + status + "\", \"players\": \"" + onlinePlayers + "\"}}";
byte[] postData = urlParameters.getBytes(StandardCharsets.UTF_8);
try (DataOutputStream wr = new DataOutputStream(connection.getOutputStream())){
wr.write(postData);
}
StringBuilder content;
try (BufferedReader br = new BufferedReader(
new InputStreamReader(connection.getInputStream()))) {
String line;
content = new StringBuilder();
while ((line = br.readLine()) != null) {
content.append(line);
content.append(System.lineSeparator());
}
}
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
connection.disconnect();
}
Thread.sleep(5 * 1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
提前致谢!
解决方案
就像@Amongalen 说你的方法playerListLoop()
是一个阻塞操作。看,你开始了一个while
循环,但你的代码中的循环永远持续下去,因为你的on
变量既没有改变,也没有类似break;
. 这意味着您的插件会卡在这种方法中。
您需要做的是创建一个新线程并让您的循环在该线程中运行,或者(以及我会推荐的)您使用BukkitScheduler
预构建到 Spigot。
同步任务
首先我们保存 id,这样我们就可以再次取消任务:
int taskID;
然后我们创建我们的任务:
- 为此,您需要一个扩展类的实例
JavaPlugin
。 - 我在这里使用了一个 lambda 表达式,但你也可以引用一个方法。
- 在这种情况下,0 是游戏时间的延迟
- 而 100 是每个循环之间的滴答时间(1 秒 = 20 滴答)
taskID = Bukkit.getScheduler().scheduleSyncRepeatingTask(YourClass.instance, () -> {
// update your API
}, 0, 100);
要取消您的任务,请执行以下操作:
Bukkit.getScheduler().cancelTask(taskID);
异步任务
如果你希望你的任务是异步的,你需要做一些不同的事情。
这次我们使用BukkitTask
界面保存我们的任务:
BukkitTask task;
然后它与同步任务非常相似:
task = Bukkit.getScheduler().runTaskTimerAsynchronously(YourClass.instance, () -> {
// update your API
}, 0, 100);
然后取消任务:
task.cancel();
推荐阅读
- java - 如何获取推送值的键
- c++ - C++ 程序中的错误(*** `./a.out' 中的错误:free():无效指针:0x00000000024a1c4f ***)
- azure - 如何将文件从 Azure 数据工厂推送到 MS Teams 频道
- excel - Worksheet_Change 未触发
- python-3.x - Scrapy - 从链接列表中提取信息
- reactjs - 搜索栏导致输入未选中
- android - 查看按钮、文本、布尔值和字符串不存在
- python - 如何在 Selenium Python 上更改 IP 地址
- node.js - dynamodb 触发器失败,但 lambda 与虚拟测试完美配合
- google-sheets - 谷歌表格:有没有办法为一个增长到重复给定次数的序列制作一个数组