思考问题的方式比“经验”之说更重要
|
雅浦岛位于北太平洋,土地面积仅102平方公里,仅有6000多名居民。这样一个“世界边缘”的偏僻岛屿上保留了人类最古老、最奇特的货币——石币。 这个不大的岛屿上流通着1.3万枚石币,形状类似中国古代的玉璧。用石质雕刻品做货币不稀奇,稀奇的是个头大。常见的雅浦岛石币直径就达到了30厘米,还有一些直径10米的超级大块头。 为什么要造这么大?为了防伪。 雅浦岛造石币的石灰岩并不稀缺,但是这个珊瑚岛不产大块石料。所以大个头的石币需要是从400公里外的帕劳岛运送来的,海滩上捡点小石子造假是不行的。不依赖材料的天然稀缺,而是以人工技术防伪,这是非常先进的理念。 而且,雅浦岛石币还是最古老的信用货币。同时代其他地区的人类制造的石币大都用美丽的软玉雕刻,可以作为装饰品佩戴,还保留了一些商品属性。 雅浦岛简单粗暴的大个儿石币显然不能“大金链子脖子上挂”,而且这个温暖的热带岛屿也不需要石头盖房子,这些石币完全无用。 无用就对了,无用才是真正的信用货币,这种别无所长、只做货币的“专业定位”可以媲美纸币。 最神奇的是石币的使用方式。 直径30厘米的“小额”石币还能一手交钱一手交货正常用,直径3米的就得几个人抬着去交换。直径超10米、重量1吨以上的“大额”石币挪一挪都困难,怎么用呢? 根本不用挪,在谁家放着就不动了。谁家的“镇宅之宝”用于交换了,在岛上都是大新闻,居民都知道。 尽管没有文字,各家杵在门口的大石币每一次易主都会迅速成为岛上的“大新闻”,留在岛民的记忆中,等于一家动钱、全岛记账——这不就是“分布式记账”的原始形态吗? 最神奇的是,石币的使用还可以虚拟化——运输途中出事故沉到海里的石币照样有主,还可以用于交易。这也不难理解,既然交易账本是口口相传的,那么这些海底的石币和杵在家门口也没什么区别,照用照记就行了。
雅浦岛人从没进入过有文字的时代,他们的石币既不精致也不美观,却体现了现代货币理论的精髓:信用,无论货币的材质多么奇葩,只要使用者“信”它有“用”,就具备了作为货币的基本条件。 为了处理非常大和长期的用途,哈希表条目使用weakreference作为键。 分两种情况讨论: (1)key 使用强引用 引用ThreadLocal的对象被回收了,但是ThreadLocalMap还持有ThreadLocal的强引用,如果没有手动删除,ThreadLocal不会被回收,导致Entry内存泄漏。 (2)key 使用弱引 引用ThreadLocal的对象被回收了,由于ThreadLocalMap持有ThreadLocal的弱引用,即使没有手动删除,ThreadLocal也会被回收。value在下一次ThreadLocalMap调用set、get、remove的时候会被清除。 比较两种情况,我们可以发现:由于ThreadLocalMap的生命周期跟Thread一样长,如果都没有手动删除对应key,都会导致内存泄漏,但是使用弱引用可以多一层保障:弱引用ThreadLocal被清理后key为null,对应的value在下一次ThreadLocalMap调用set、get、remove的时候可能会被清除。 因此,ThreadLocal内存泄漏的根源是:由于ThreadLocalMap的生命周期跟Thread一样长,如果没有手动删除对应key就会导致内存泄漏,而不是因为弱引用。 ThreadLocal最佳实践 通过前面几小节我们分析了ThreadLocal的类设计以及内存模型,同时也重点分析了发生内存泄露的条件和特定场景。最后结合项目中的经验给出建议使用ThreadLocal的场景:
综合上面的分析,我们可以理解ThreadLocal内存泄漏的前因后果,那么怎么避免内存泄漏呢? 答案就是:每次使用完ThreadLocal,建议调用它的remove()方法,清除数据。
另外需要强调的是并不是所有使用ThreadLocal的地方,都要在最后remove(),因为他们的生命周期可能是需要和项目的生存周期一样长的,所以要进行恰当的选择,以免出现业务逻辑错误! (编辑:甘孜站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |

