代码优化之道 – 异步

作者: IzzelAliz 分类: 编程语言 - Program Language 发布时间: 2018-03-15 22:43

插件创作过程中,你可能可以使用以下技巧降低你的插件对服务端的负载。

异步化

需要注意的是,异步并不会减少服务端负载,但是异步能够减少主线程阻塞的时间,防止服务器因为你的操作而卡顿。
另外,多线程操作会涉及到其他的问题,比如资源抢占,如果没有很好的处理就会像这样:

一些对异步操作的警告

Bukkit API 仅有的几个稳妥的支持异步的方法有
* Player#sendMessage
* Player#sendPluginMessage
剩下的都有或多或少的隐患。

如果需要在异步线程进行操作,可以使用调度器执行主线程任务,如

Player player = ...;
Bukkit.getScheduler().runTask(() -> player.setHealth(20), Plugin.instance);

异步 – 文件读写 / 网络 IO

并不是所有 IO 操作都需要异步,例如插件初始化时,这时并没有玩家加入服务器,你可以放心操作而不用担心造成卡顿。

在 NodeJS 中,文件的读写使用了回调模式(Callback),这是一个可以学习的模式。

var fs = require("fs")

fs.readFile('input.txt', (err, data) => {
    console.log(data.toString())
})

这里的读写完全在异步线程中完成,Java 中也可以这么做:将数据在异步读取,然后返回主线程进行数据操作,从而避免可能的 IO 阻塞。

// 线程池
private static ExecutorService pool = Executors.newFixedThreadPool(1);

// 读取文件
private static void readFile(String file, Consumer<byte[]> callback) {
    pool.execute(() -> {
        byte[] arr = Files.toString(new File(file), Charset.forName("utf-8")).getBytes();
        // 返回主线程
        Bukkit.getScheduler().runTask(/*插件实例*/ instance, () -> callback.accept(arr));
    });
}

readFile("input.txt", arr -> System.out.println(arr));

文件 IO 的等待并不会非常严重,但是在有些情况下仍然会卡顿。至于网络通信,那就一定不能在主线程完成了,比如更新检测。

未完.

发表评论

电子邮件地址不会被公开。 必填项已用*标注

标签云