Java NIO(9) : 状态机

今天是小密圈《进击的Java新人》第十八周第一课。我们继续上周所讲的异步模型。

上一节课我们使用了状态机来写服务端逻辑,那么状态机到底是什么呢?

状态机本质上就是能保存状态的一个对象。在状态机上进行某一个操作(或者说发生了什么动作),状态机就会从一个状态迁移到另一个状态,以我们上节课的 EpollTask 为例。整个程序中,我们定义了一个state变量,当发生一个读或者写动作的时候,这个state变量就会变化。

我们用一个图来表示:

在开始的时候,EpollTask中的state变量为0,接受到被除数的时候,状态变成1,然后发送通知给客户端以表示已经收到一个被除数了。然后再收到除数。这里是关键了,通过代码我们可以看到接收被除数和除数的时候都是接收了一个整数,我们是通过什么知道现在发送的是第一个数还是第二个数的呢?没错,就是通过state变量。

这就是状态机。状态机定义了状态,以及在这个状态下所能接受的动作(或者说操作)。这些状态和操作一起组成了一个状态机。

不知道大家是否还记得这一课:Java中的设计模式:适配与装饰 - 知乎专栏

在这一课里,我留了一个作业,就是把一个表达式拆分成各种token,其实这就是一个词法分析器。自动机是词法分析的一个利器,例如,有一个表达式,表达式里包含了变量和数字。如何把这些变量和数字分析出来呢?

比如,x1 * x2 + y1 * 28,这样一个表达式,我们要从中分析出,x1, *, y1, +, 28这些token。状态机是一个非常好用的工具。我们可以这样定义词法分析的状态机:

一开始是状态0,如果读到一个字符进来,就变成状态1,状态1可以接受字母或者数字,接受一个字母或者数字以后,仍然是状态1。如果这进有一个新的字符,那么这个字符不被接受,然后,状态机会回到状态0,并且,这表示着一个变量名就被分析出来了。另外三个分支,我就不一一解释了。

我们还是以具体的例子来说明,一开始状态机的状态是S0,第一个输入字符是 x,是一个字母,然后状态机就会变成状态S1,下一个字符是数字1,这是合法输入,接受它,并且状态机仍然的状态仍然是S1。下一个是 * ,这是一个S1不接受的输入。那么这时候,x1就被识别出来了。然后,状态机回到S0,在S0的状态下,处理 * 号,就会进入状态S4。在S4状态下,不能接受任务字符为合法字符,那么下一个x,就会使得状态机回到S0,依次反复循环,最后就把所有的字符都识别出来了。

好了。今天的内容很简单,就是昨天课程的一个后续而已。动手操作一下吧:

“I have a good news :\"hello world\""

这样一个字符串里包含了一些标点和单词,试试能不能把这个标点和单词分别标记出来。要注意,由于字符串是用双引号引起来的,所以如果句子中出现了双引号,就需要使用 \ ,这个符号来进行转义。分析的时候,\ 是不保留的。例如,上面的句子分析完了以后就是

I, have, a, good, news, :, ", hello, world, "

上一节课:Java NIO(8) : 异步模型之状态机

下一节课:Java NIO(10):异步模型之Callback

目录:课程目录

编辑于 2017-06-20

文章被以下专栏收录