博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java8 Lambda表达应用 -- 单线程游戏server+异步数据库操作
阅读量:5051 次
发布时间:2019-06-12

本文共 3862 字,大约阅读时间需要 12 分钟。

前段时间我们游戏server升级到开发环境Java8,这些天,我再次server的线程模型再次设计了一下,耗费Lambda表情

LambdaJava代码。特别是丑陋不堪的匿名内部类,这篇文章主要就是想和大家分享这一点。

线程模型

首先简介一下我们游戏server的线程模型。大致例如以下图所看到的:

Netty线程池仅仅处理消息的收发,当Netty收到消息之后。会交给游戏逻辑线程处理。因为是单线程在处理游戏逻辑,所以每个消息必须非常快处理完。也就是说,不能有数据库等耗时操作。不然逻辑线程非常可能会被卡住。为了不卡住逻辑线程,数据库操作由单独的线程池来处理。

逻辑线程发起数据库操作后便马上返回继续处理其它消息。数据库线程池处理完成后。再通知逻辑线程,从而达到了异步数据库操作的效果。

GameAction

Netty部分的网络代码,在收到消息后。会依据消息找到相应的Action,然后运行。

详细代码省略,以下是简化后的GameAction的代码:

public abstract class GameAction {        /**     * 在逻辑线程里处理消息.     * @param gs     * @param req 请求消息     */    public void execute(GameSession gs, Object req) {        GameLogicExecutor.execute(() -> {            doExecute(gs, req);        });    }        // 子类实现    public abstract void doExecute(GameSession gs, Object req);    }
execute()方法里,使用了Lambda表达式来实现Runnable接口。

GameLogicExecutor

GameLogicExecutor是游戏逻辑运行线程,代码例如以下所看到的:

import java.util.concurrent.Executor;import java.util.concurrent.Executors;/** * 游戏逻辑线程. */public class GameLogicExecutor {        // todo 限制队列长度    private static final Executor executor = Executors.newSingleThreadExecutor();        /**     * 把游戏逻辑放到队列.     * @param gameLogic      */    public static void execute(Runnable gameLogic) {        executor.execute(gameLogic);    }    }

GetPlayerListAction

以下看一个详细的GameAction实现,这个Action依据用户ID返回用户创建的玩家列表。代码例如以下:

import java.util.List;public class GetPlayerListAction extends GameAction {    @Override    public void doExecute(GameSession gs, Object req) {        int userId = (Integer) req;        PlayerDao.getPlayerList(userId, (List
players) -> { gs.write(players); }); } }
如果请求參数是玩家ID。doExecute()方法并没有等待数据库操作。而是立即就返回了。传递给DAO的回调对象是个Lambda表达式,在回调方法里,玩家列表通过GameSession被写到client(
这仅仅是演示,实际的响应消息可能是protobuf或JSON)。

PlayerDao

import java.util.ArrayList;import java.util.List;public class PlayerDao {        public static void getPlayerList(int userId, DbOpCallback
> cb) { DbOpExecutor.execute(() -> { try { List
players = getPlayerList(userId); cb.ok(players); } catch (Exception e) { cb.fail(e); } }); } // 耗时的数据库操作 private static List
getPlayerList(int userId) { return new ArrayList<>(); } }

getPlayerList()方法接收两个參数。第一个參数是用户ID,第二个參数是个callback,当数据库操作完成(成功或失败)时。会通知这个callback。DAO内部使用的可能是JDBC或MyBatis等,总之是耗时的操作,由数据库线程池运行。

DbOpExecutor

DbOpExecutor的代码比較简单。和GameLogicExecutor相似,例如以下所看到的:

import java.util.concurrent.Executor;import java.util.concurrent.Executors;/** * 数据库操作线程池. */public class DbOpExecutor {        // todo 依据cpu数等确定线程数    private static final Executor executor = Executors.newFixedThreadPool(4);        /**     * 把数据库操作放进队列.     * @param dbOp      */    public static void execute(Runnable dbOp) {        executor.execute(dbOp);    }    }

DbOpCallback

最后看一下DbOpCallback代码:

/** * 数据库操作回调. * @param 
*/@FunctionalInterfacepublic interface DbOpCallback
{ /** * 处理数据库返回结果. * @param result */ void handleResult(T result); /** * 数据库操作正常结束. * @param result */ default void ok(T result) { // 在游戏逻辑线程里处理结果 GameLogicExecutor.execute(() -> { try { handleResult(result); } catch (Exception e) { // todo 处理异常 } }); } /** * 数据库操作出现异常. * @param e */ default void fail(Exception e) { // todo 处理异常 } }
@FunctionalInterface说明这是一个
函数式接口,简单的说,就是仅仅有一个抽象方法的接口。接口的
default方法是Java8的新语法,详细请參考Java8相关方面的资料。ok()方法确保数据库操作的结果是在逻辑线程里处理。

结论

上面的代码。在Java8之前用匿名内部类也是能够写的,仅仅是相比Lambda表达式,更加冗长丑陋而已。另外要注意,上面的代码仅仅是简化后的演示样例代码,并不是真实代码。

假上面的代码设想到自己的项目,还需要注意的是异常处理。

版权声明:本文博主原创文章,博客,未经同意不得转载。

转载于:https://www.cnblogs.com/bhlsheji/p/4865674.html

你可能感兴趣的文章
图王:刺客——运筹帷幄善于在变化中找到方向的站长
查看>>
Safari无痕浏览影响localStorage
查看>>
POJ 3368 Frequent values (RMQ,4级)
查看>>
java 练习题3
查看>>
对象生命周期的简单理解
查看>>
c# 日志记录 行号
查看>>
CSS3---12.过渡动画
查看>>
[NOI1995]石子合并 四边形不等式优化
查看>>
vim 实现begin end 配对 使用matchit插件
查看>>
linux挂载磁盘以及扩容主分区
查看>>
[转]Python模块学习:threading 多线程控制和处理
查看>>
PHP链接sqlserver出现中文乱码
查看>>
[计算机]Alan Perlis人物简介
查看>>
Android-----第三方 ImageLoader 的简单配置和使用
查看>>
零基础入门Python3-详解分支
查看>>
js数组去重
查看>>
A. E-mail
查看>>
C# 反射机制以及方法
查看>>
C# Socket服务端与客户端通信(包含大文件的断点传输)
查看>>
美丽汤的请求 - 小甜饼豆瓣爬虫
查看>>