弱表(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") end
strongTable[2] = function() print("i am the second element") end
strongTable[3] = {10, 20, 30} print(table.getn(strongTable)) -- 3
collectgarbage()
print(table.getn(strongTable)) -- 3

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

weakTable = {}
weakTable[1] = function() print("i am the first element") end
weakTable[2] = function() print("i am the second element") end
weakTable[3] = {10, 20, 30} setmetatable(weakTable, {__mode = "v"}) -- 设置为弱表 print(table.getn(weakTable))     -- 3 ele = weakTable[1]             -- 给第一个元素增加一个引用
collectgarbage()
print(table.getn(weakTable))       -- 1,第一个函数引用为1,不能gc ele = 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

Lua中的weak表——weak table(转)的更多相关文章

  1. Lua中的weak表——weak table

    弱表(weak table)是一个很有意思的东西,像C++/Java等语言是没有的.弱表的定义是:A weak table is a table whose elements are weak ref ...

  2. Openvswitch原理与代码分析(5): 内核中的流表flow table操作

      当一个数据包到达网卡的时候,首先要经过内核Openvswitch.ko,流表Flow Table在内核中有一份,通过key查找内核中的flow table,即可以得到action,然后执行acti ...

  3. lua中,两种json和table互转方法的效率比较

    lua中json和table的互转,是我们在平时开发过程中经常用到的.比如: 在用lua编写的服务器中,如果客户端发送json格式的数据,那么在lua处理业务逻辑的时候,必然需要转换成lua自己的数据 ...

  4. Lua中的元表与元方法

    [前言] 元表对应的英文是metatable,元方法是metamethod.我们都知道,在C++中,两个类是无法直接相加的,但是,如果你重载了“+”符号,就可以进行类的加法运算.在Lua中也有这个道理 ...

  5. Lua中的元表与元方法学习总结

    前言 元表对应的英文是metatable,元方法是metamethod.我们都知道,在C++中,两个类是无法直接相加的,但是,如果你重载了"+"符号,就可以进行类的加法运算.在Lu ...

  6. #在lua中的运用

    在lua中"#"表示返回表长度或字符串长度 例子一: a = "Hello " b = "World" print("Concat ...

  7. Lua中的一些库(1)

    [数学库] 数学库(math)由一组标准的数学函数构成.这里主要介绍几个常用的函数,其它的大家可以自行百度解决. 三角函数(sin,cos,tan……)所有的三角函数都使用弧度单位,可以用函数deg( ...

  8. Lua中的metatable详解

    转自:http://www.jb51.net/article/56690.htm Lua 中 metatable 是一个普通的 table,但其主要有以下几个功能: 1.定义算术操作符和关系操作符的行 ...

  9. Lua弱表Weak table

    定义:弱表的使用就是使用弱引用,很多程度上是对内存的控制. 1.weak表示一个表,它拥有metatable,并且metatable定义了__mode字段. 2.弱引用不会导致对象的引用计数变化.换言 ...

随机推荐

  1. 定义Java类的数组的问题

    定义了一个类: class Student{ private int Id; public int getId() { return Id; } public void setId(int id) { ...

  2. Mina框架断包、粘包问题解决方式

    Mina框架断包.粘包问题解决方式 Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP.UDP/IP协议栈的通信框架(当然.也能够提供JAVA 对象的序 ...

  3. extjs在form表单提交成功、故障响应信息

    类别Ext.form.Action.Submit 处理表单Form数据并返回response类对象. 这个类的仅在形式实例Form{@link Ext.form.BasicForm#submit 提交 ...

  4. 怎样在万网加入Lync Online SRV记录

    万网已经支持SRV记录解析了,可是有好几个朋友问我怎么加入SRV记录(假设域名提供商不支持,能够通过DNSPOD来实现),过程例如以下 1:绑定域名至Office 365 略,请查看我的视频或者博客中 ...

  5. Windows Phone开发(45):推送通知大结局——Raw通知

    原文:Windows Phone开发(45):推送通知大结局--Raw通知 为什么叫大结局呢?因为推送通知服务就只有三种,前面扯了两种,就剩下一种--Raw通知. 前面我们通过两节的动手实验,相信大家 ...

  6. J2EE的13个规范之JDBC

    假设让你接触一样新的东西.你可能感觉无所适从,可是假设本来就是旧事物的话,你学习起来还难吗? 一.ODBC,我们的老朋友 ODBC(Open Database Connectivity)是微软公司与数 ...

  7. EJB_消息驱动发展bean

    消息驱动发展bean Java信息服务(Java MessageService) Java 信息服务(Java Message Service,简称 JMS)是用于訪问企业消息系统的开发商中立的API ...

  8. java线程例子登山

    Through its implementation, this project will familiarize you with the creation and execution of thr ...

  9. svn 使用(一个)

    一个. 安装svn  server(操作系统centos) yum install subversion 通过 subversion -v 如果成功安装命令来查看 温馨提示不承担任何subversio ...

  10. VMware vSphere 服务器虚拟化之十八桌面虚拟化之安装View Composer服务器

                        VMware vSphere 服务器虚拟化之十八桌面虚拟化之安装View Composer服务器      View Compose服务可安装在管理虚拟机的vC ...