事件驱动模型

在这里插入图片描述

1. 概念

事件驱动:事件驱动是指在持续事务管理过程中,进行决策的一种策略,即跟随当前时间点上出现的事件,调动可用资源,执行相关任务,使不断出现的问题得以解决,防止事务堆积。事件驱动的核心自然是事件,从事件角度说,事件驱动程序的基本结构是由一个事件收集器、一个事件发送器和一个事件处理器组成。

2. 作用

事件驱动编程是一种编程范式,这里程序的执行流由外部事件来决定。它的特点是包含一个事件循环,当外部事件发生时使用回调机制来触发相应的处理。基于事件驱动的程序可以实时响应所关心的事件,可以实现模块之间的解耦、实现异步任务、跟踪状态变化。

3. 应用场景

Windows 本身是基于事件驱动模型的,目前大部分的UI编程也都是事件驱动模型。比如你现在的鼠标点击,按下鼠标就会产生一个onClick()事件,因为平台有注册相应的回调事件,每当点击就会触发该事件,然后交给对应的事件处理器进行处理。

事件驱动的大体逻辑如下:

  • 存在一个消息队列,用于存储的各种事件
  • 当触发了某个事件,就向队列中添加该事件
  • 有循环不断从队列中取出事件,根据派发的不同事件,做相应的处理操作,调用不同的函数处理
  • 事件一般都保存有自己的处理函数指针,每个事件都有独立的处理函数

4. 具体实现

个人简单理解:

事件驱动就是首先得有一个队列用于缓存事件,相当于一个信道。队列尾会一直添加触发的事件消息,之后有一个处理事件的循环,一直会从队列头取出事件,并执行事件自带的回调函数。

下面用事件驱动的方式【逆序一个文件】

1. 异步IO库

  • readline:读事件
  • writeline:写事件
  • stop:停止事件
  • loop:处理事件的循环

文件名:async-lib.lua

#!/usr/local/bin/lua

-- local queue = require "deque" -- 需要配置 path
dofile("../dataStructure/deque.lua") -- 路径不用管,就是导入自定义的deque

local queue = deque() 
local lib = {} 

function lib.readline(stream, callback) 
    local cmd = function()
        callback(stream:read())
    end
    queue.push_back(cmd)
end

function lib.writeline(stream, line, callback) 
    local cmd = function() 
        callback(stream:write(line))
    end
    queue.push_back(cmd)
end 

function lib.stop() 
    queue.push_back("stop")
end

function lib.loop()
    print("开始循环工作-------")
    while true do 
        local cmd = queue.pop_front() 
        if cmd == "stop" then print("[ cmd = 'stop' ]") break end 
        cmd()
    end
    print("结束循环工作-------")
end

return lib

2. 事件驱动

可以忽略一些打印信息的代码,方便之后的输出信息查看,理解运行的逻辑。

先调用getline进入文件准备开始读取第一行,然后执行loop开始去取第一条指令。这里getline是将自己作为回调函数注册进readline,指令一直运行相当于递归一直调用getline,并且从流中读入的数据作为getline的参数line存入表t中。

在读到文件尾,getline中会调用putline函数,同理递归的调用putline,逆序的输出了文件内容。

作为一种典型的事件驱动场景,由于主循环位于库async-lib.lua中,因此所有的循环都消失了,这些循环被以事件区分的递归调用所取代。

文件名:event_file.lua

#!/usr/local/bin/lua

local lib = require "async-lib"

local file_in = io.open("file_in.txt", "a+")
local input = io.input(file_in) 
local file_out = io.open("file_out.txt", "w+")
local output = io.output(file_out) 

local t = {} 
local i = 0
local label_putline = 0 
local label_getline = 0

local function putline() 
    if label_putline == 0 then  
        print("----------------------------------------")
        print("getline 已完成使命(读完文件所有内容)")
        print("----------------------------------------")
    end 
    
    print("现在调用: putline()")
    i = i - 1
    if i == 0 then 
        lib.stop() 
    else 
        lib.writeline(output, t[i] .. "\n", putline)
        print(string.format("第[ %d ]写入", label_putline + 1))
        label_putline = label_putline + 1
    end
end

local function getline(line) 
    if label_getline == 0 then 
        print("----------------------------------------")
        print("getline 开始读文件内容")
        print("----------------------------------------")
    end 
    print("现在调用:getline(line)")
    if line then 
        t[#t + 1] = line 
        lib.readline(input, getline) 
        print(string.format("第[ %d ]读入", label_getline + 1))
        label_getline = label_getline + 1
    else 
        i = #t + 1 
        putline() 
    end 
end

lib.readline(input, getline) -- 读取第一行开始
lib.loop() -- 运行主循环
io.close(file_in)
io.close(file_out)

3. 协程重写

协程可以让我们使用事件循环来简化循环的代码,其核心思想是使用协程运行主要代码,即在每次调用库时将回调函数设置为唤醒协程的函数,然后让出执行权。

下面例子是使用异步库运行同步代码

文件名:coroutine_file.lua

#!/usr/local/bin/lua

local lib = require "async-lib"

function run(code) 
    local co = coroutine.wrap(function()
        code() 
        lib.stop() -- 所有code逻辑运行完,停止
    end)
    co() -- 开始运行,然后进到code()逻辑
    -- 阻塞在第一次yield,然后执行lib.loop
    lib.loop() -- 开始事件循环 
end

function putline(stream, line) 
    local co = coroutine.running() 
    local callback = (function() coroutine.resume(co) end)
    lib.writeline(stream, line, callback)
    coroutine.yield()
end

function getline(stream, line) 
    local co = coroutine.running() 
    local callback = (function(l) coroutine.resume(co, l) end)
    lib.readline(stream, callback)
    local line = coroutine.yield()
    return line
end

run(function() 
    local t = {} 
    local file_in = io.open("file_in.txt", "a+")
    local file_out = io.open("file_out.txt", "w+")
    local input = io.input(file_in) 
    local output = io.output(file_out) 

    while true do 
        local line = getline(input) 
        if not line then break end 
        t[#t + 1] = line 
    end 

    for i = #t, 1, -1 do 
        putline(output, t[i] .. "\n")
    end 

    io.close(file_in)
    io.close(file_out)
end)

  1. 文件:file_in.txt
start
1 line 
2 line 
3 line 
4 line 
5 line 
end
  1. 文件:file_out.txt
end
5 line 
4 line 
3 line 
2 line 
1 line 
start
  1. 输出
开始循环工作-------
----------------------------------------
getline 开始读文件内容
----------------------------------------
现在调用:getline(line)[ 1 ]读入
现在调用:getline(line)[ 2 ]读入
现在调用:getline(line)[ 3 ]读入
现在调用:getline(line)[ 4 ]读入
现在调用:getline(line)[ 5 ]读入
现在调用:getline(line)[ 6 ]读入
现在调用:getline(line)[ 7 ]读入
现在调用:getline(line)
----------------------------------------
getline 已完成使命(读完文件所有内容)
----------------------------------------
现在调用: putline()[ 1 ]写入
现在调用: putline()[ 2 ]写入
现在调用: putline()[ 3 ]写入
现在调用: putline()[ 4 ]写入
现在调用: putline()[ 5 ]写入
现在调用: putline()[ 6 ]写入
现在调用: putline()[ 7 ]写入
现在调用: putline()
[ cmd = 'stop' ]
结束循环工作-------

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Java事件驱动模型可以理解为一种异步编程机制,其核心在于监听事件并在事件发生时触发相应的处理逻辑。这种模型适用于需要高并发处理的场景,如网络编程、GUI编程等。 在Java中,事件驱动模型通常采用观察者模式实现。观察者模式是指当一个对象发生状态变化时,会通知其他观察者对象,让它们进行相应的处理。在事件驱动模型中,事件源对象会发出事件,观察者对象会监听事件并进行处理。 Java中的事件驱动模型通常包含以下几个组件: 1. 事件源(Event Source):事件源是指触发事件的对象,通常是某个组件或者方法。 2. 事件(Event):事件是指某个状态的变化或者某个动作的完成。事件通常包含事件源对象和事件类型。 3. 监听器(Listener):监听器是指负责监听事件的对象。在Java中,监听器通常实现了某个接口,如ActionListener、MouseListener等。 4. 事件处理器(Event Handler):事件处理器是指负责处理事件的对象。在Java中,事件处理器通常是监听器对象的一个方法,如actionPerformed()、mouseClicked()等。 Java中的事件驱动模型可以应用于多个场景,如GUI编程、网络编程、消息队列等。在实际应用中,需要根据具体的需求和场景,选择合适的事件驱动框架和技术,如Java AWT、Java Swing、Java NIO等。同时,需要注意事件驱动模型的线程安全问题,避免多线程并发访问导致的数据不一致或者死锁等问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ღCauchyོꦿ࿐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值