博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Lua中的weak表——weak table(转)
阅读量:6895 次
发布时间:2019-06-27

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

  弱表(weak table)是一个很有意思的东西,像C++/Java等语言是没有的。弱表的定义是:A weak table is a table whose elements are weak references,元素为弱引用的表就叫弱表。有弱引用那么也就有强引用,有引用那么也就有非引用。我们先要厘这些基本概念:变量、值、类型、对象。

  (1)变量与值:Lua是一个dynamically typed language,也就是说在Lua中,变量没有类型,它可以是任何东西,而值有类型,所以Lua中没有变量类型定义这种东西。另外,Lua中所有的值都是第一类值(first-class values)。

  (2)Lua有8种基本类型:nil、boolean、number、string、function、userdata、thread、table。其中Nil就是nil变量的类型,nil的主要用途就是一个所有类型之外的类型,用于区别其他7中基本类型。

  (3)对象objects:Tables、functins、threads、userdata。对于这几种值类型,其变量皆为引用类型(变量本身不存储类型数据,而是指向它们)。赋值、参数传递、函数返回等都操作的是这些值的引用,并不产生任何copy行为。

   

  Lua的垃圾回收机制:gc是很多语言的常见机制,让程序员拜托复杂易出错的内存管理。

  定义:Lua manages memory automatically by running a garbage collector to collect all dead objects (that is, objects that are no longer accessible from Lua). 

  三点理解:(1)gc自动运行,也可以手动调用;(2)自动收集的目标是引用计数为0的对象;(3)dead objects:不能访问到的对象,没有引用指向它了,当然就是访问不到的了,也就等同于垃圾内存了。

 

  weak table的定义:

  (1)weak表是一个表,它拥有metatable,并且metatable定义了__mode字段;

  (2)weak表中的引用是弱引用(weak reference),弱引用不会导致对象的引用计数变化。换言之,如果一个对象只有弱引用指向它,那么gc会自动回收该对象的内存。

  (3)__mode字段可以取以下三个值:k、v、kv。k表示table.key是weak的,也就是table的keys能够被自动gc;v表示table.value是weak的,也就是table的values能被自动gc;kv就是二者的组合。任何情况下,只要key和value中的一个被gc,那么这个key-value pair就被从表中移除了( In any case, if either the key or the value is collected, the whole pair is removed from the table)。

  对于普通的强引用表,当你把对象放进表中的时候,就产生了一个引用,那么即使其他地方没有对表中元素的任何引用,gc也不会被回收这些对象。那么你的选择只有两种:手动释放表元素或者让它们常驻内存。

strongTable = {}strongTable[1] = function() print("i am the first element") endstrongTable[2] = function() print("i am the second element") endstrongTable[3] = {10, 20, 30}print(table.getn(strongTable))            -- 3collectgarbage()                        print(table.getn(strongTable))            -- 3

  但是,在编程环境中,有时你并不确定手动给一个键值赋nil的时机,而是需要等所有使用者用完以后进行释放,在释放以前,是可以访问这个键值对的。这种时候,weak表就派上用场了。关于weak table的理解,看下面这个小例子:

weakTable = {}weakTable[1] = function() print("i am the first element") endweakTable[2] = function() print("i am the second element") endweakTable[3] = {10, 20, 30}setmetatable(weakTable, {__mode = "v"})        -- 设置为弱表print(table.getn(weakTable))                -- 3ele = weakTable[1]                    -- 给第一个元素增加一个引用collectgarbage()print(table.getn(weakTable))               -- 1,第一个函数引用为1,不能gcele = nil                             -- 释放引用collectgarbage()print(table.getn(weakTable))                -- 0,没有其他引用了,全部gc

  当然在实际的代码过程中,我们不一定需要手动collectgarbage,因为该函数是在后台自动运行的,它有自己的运行周期和规律,对编程者来说是透明的。

  注意:只有拥有显示构造的对象类型会被自动从weak表中移除,值类型boolean、number是不会自动从weak中移除的。而string类型虽然也由gc来负责清理,但是string没有显示的构造过程,因此也不会自动从weak表中移除,对于string的内存管理有单独的策略。

  基于weak表的简单应用:

  (1)记忆函数:一个相当普遍的编程技术是用空间来换取时间。你可以通过记忆函数结果来进行优化,当你用同样的参数再次调用函数时,它可以自动返回记忆的结果。将函数的输入和输出分别作为key和value放在一个weak table里面,调用函数之前先查看有无现成的结果,有就返回,没有就调用函数,然后将结果存入表中。由于是weak table,此表会定期自动清理掉不再有引用的键值对。

  (2)关联对象属性:Lua本身使用这种技术来保存数组的大小。table库提供了一个函数来设定数组的大小,另一个函数来读取数组的大小。当你设定了一个数组的大小,Lua 将这个尺寸保存在一个私有的weak table,索引就是数组本身,而value就是它的尺寸。

  同样的,当我们需要给任一对象添加一个属性的时候,可以在外部单独做一弱key表,然后以对象为key值,属性值为value。这样即可以方便的访问这个属性,也不影响该对象的释放。而且对象本身没任何修改,能很好的保持对象本身的独立性。

   (3)带有默认值的表:

  有两种实现方法,第一种方法,使用关联对象属性的方法,将表作为key,默认值作为value,存到一个弱key的weak表中:

local defaults = {}setmetatable(defaults, {_mode = "k"})local mt = {__index = function(t) return defaults[t] end}function setDefault(t, d)    defaults[t] = d    setmetatable(t, mt)end

  第二种方法,针对不同的metatable来进行优化,对于每一个具体的默认值,生成一个与之对应的metatable,然后以默认值为key,metatable为value,存到一个弱value的weak表中:

metas = {}setmetatable(metas, {__mode = "v"})setdefault = function (t, d)    local mt = metas[d]    if mt == nil then        mt = {__index = function() return d end}        metas[d] = mt    end    setmetatable(t, mt)end

  两种方式各有利弊,第一种方法对于每一个table都需要添加一个键值对,但是公用一个metatable。第二种方法需要许多个不同的metatable,但拥有相同默认值的table共用一个metatable,并且weak表要比第一种方法小。如果你的代码环境中有很多个table,但常用默认值只有那么几种,建议选择第二种方法,否则就选择第一种方法。

1、 Lua脚本中的标签方法由宿主语言即java语言调用,Lua脚本实际上被LuaJ翻译成了java的类实例方法。整个调用过程在一个单线程中运行。

2、 Java语言调用Lua脚本标签方法时,会传递一些参数,标准参数一般是request或deltaMo。这些参数由调用接口转换成Lua的标签方法的参数,它是一个Lua table结构。比如java的request参数转成Lua参数就是moSelf,而deltaMo参数转换成Lua就是incData。

http://www.cnblogs.com/sifenkesi/p/3850760.html

转载于:https://www.cnblogs.com/softidea/p/5242970.html

你可能感兴趣的文章
使用PHP+Sphinx建立高效的站内搜索引擎
查看>>
Fastjson中以is打头出现的问题,会生成两个变量
查看>>
HTTP API网关选择之一Kong介绍
查看>>
基于Redis构建10万+终端级的高性能部标JT808协议的Gps网关服务器(转)
查看>>
把搜狗输入法词库导入Google拼音输入法
查看>>
利用反射将IDataReader读取到实体类中效率低下的解决办法
查看>>
用ndp部署storm应用
查看>>
【Java】监控远程服务器JVM
查看>>
JVM系列第12讲:JVM参数之查看JVM参数
查看>>
Spring中加载xml配置文件的六种方式
查看>>
android Fragments详解二:创建Fragment
查看>>
知道创宇 - 中文版putty后门事件分析
查看>>
电子政务信息交换平台与数据中心的构建(转)
查看>>
妄撮小游戏的开发思想-Android开发资料-《妄撮(撕开美女衣服)》游戏源代码外传...
查看>>
用ethtool确定多网卡Linux服务器网口位置
查看>>
Perl分割字符串的一个精妙的写法
查看>>
零点祝福
查看>>
上下文属性监听
查看>>
【小白的CFD之旅】10 敲门实例
查看>>
POI文件导出至EXCEL,并弹出下载框
查看>>