﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-磨刀不误砍柴工</title><link>http://www.blogjava.net/weiwei/</link><description>合抱之木，生于毫末；九层之台，起于累土；千里之行，始于足下。</description><language>zh-cn</language><lastBuildDate>Tue, 28 Apr 2026 19:00:09 GMT</lastBuildDate><pubDate>Tue, 28 Apr 2026 19:00:09 GMT</pubDate><ttl>60</ttl><item><title>字符编码知识</title><link>http://www.blogjava.net/weiwei/articles/410765.html</link><dc:creator>liwei5891</dc:creator><author>liwei5891</author><pubDate>Sat, 08 Mar 2014 04:57:00 GMT</pubDate><guid>http://www.blogjava.net/weiwei/articles/410765.html</guid><wfw:comment>http://www.blogjava.net/weiwei/comments/410765.html</wfw:comment><comments>http://www.blogjava.net/weiwei/articles/410765.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weiwei/comments/commentRss/410765.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weiwei/services/trackbacks/410765.html</trackback:ping><description><![CDATA[<div>1.计算机信息的存储与处理</div><div>计算机信息（包括字母、各种符号、图形符号）分为：</div><div>|--数据信息</div><div><span style="white-space:pre">	</span>|--数值</div><div><span style="white-space:pre">	</span>|--非数值</div><div>|--控制信息</div><div>计算机信息以二进制编码方式存入计算机并得以处理。</div><div>这种二进制代码就叫字符编码。</div><div></div><div>2.西文字符集</div><div>使用最广泛的西文字符集及编码是：ASCII字符集 和 ASCII码</div><div>(American Standard Code for Information Interchange)美国标准信息交换码</div><div>使用7个或8个二进制进行编码的方案，最多可以给256个字符编码。</div><div>基本的ASCII字符集共有128个字符，其中96个是可打印字符。</div><div>A为65，0为48</div><div>大小写之间差32</div><div></div><div>3.MBCS</div><div>为扩充ASCII编码，不同国家地区制定了不同的标准。它些使用2个字节代表一个字符的各种汉字延伸编码方式，称为ANSI编码 (American Nation Standards Institute-美国国家标准学会）又称为：Muilti-Bytes Charecter Set 多字节字符集</div><div>简体中文下,ANSI表示GB2312编码</div><div></div><div>由于不同ANSI编码互不兼容，因此将属于两种语言的文字存储在同一段ANSI编码的文本中。另外同一个编码值在不同的编码体系代表不同的字，这样容易造成混乱。这就导致了UNICODE码的诞生。</div><div></div><div>所有的编码都有一个转换器可以转到unicode,而unicode也可以转换到其它所有的编码</div><div></div><div>3.GB2312</div><div>中国国家标准总局发布了一系列汉字字符集国家标准编码，其中最有影响的是 1980年发布的GB 2312-1980,因其使用非常普遍，也被称为国标码。</div><div></div><div>GB2312由6763个常用汉字和682个全角的非汉字字符组成。汉字根据使用频率分两级,一级3755个，二级3008个。采用二维矩阵编码法对所有字条进行编码。94行94列的方阵，每一行称为一个区，每一列称为一个位。</div><div></div><div></div><div>4.UNICODE编码</div><div>它是一个大而全的编码，包含了世界上所有的符号，无论是英文，日文，还是中文。现在的规模可以容纳100多万个符号，每个符号的编码都不一样。</div><div>虽然统一了编码方式，但它的效率不高。对存储和传输来说都很耗资源</div><div></div><div>5.UTF-8</div><div>为提高 unicode的编码效率，出现了UTF-8编码。</div><div>它可根据不同的符号自动选择编码的长短。</div><div></div><div></div><div></div><div></div><img src ="http://www.blogjava.net/weiwei/aggbug/410765.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weiwei/" target="_blank">liwei5891</a> 2014-03-08 12:57 <a href="http://www.blogjava.net/weiwei/articles/410765.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>足球规则-视频</title><link>http://www.blogjava.net/weiwei/articles/407865.html</link><dc:creator>liwei5891</dc:creator><author>liwei5891</author><pubDate>Sat, 21 Dec 2013 15:41:00 GMT</pubDate><guid>http://www.blogjava.net/weiwei/articles/407865.html</guid><wfw:comment>http://www.blogjava.net/weiwei/comments/407865.html</wfw:comment><comments>http://www.blogjava.net/weiwei/articles/407865.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weiwei/comments/commentRss/407865.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weiwei/services/trackbacks/407865.html</trackback:ping><description><![CDATA[<div>足球规则第一章 比赛场地</div><div>http://you.video.sina.com.cn/api/sinawebApi/outplayrefer.php/vid=1322621_1279208024_OErhTyU4XjbK+l1lHz2stqkP7KQNt6nki229uVKsJQxdQ0/XM5GYYd8F5ivXFokbpWFMR5o9c/wn/s.swf</div><div></div><div>足球规则第二章 球</div><div>http://you.video.sina.com.cn/api/sinawebApi/outplayrefer.php/vid=10939506_1279208024_akzmTCo6BmfK+l1lHz2stqkP7KQNt6nki229uVKsJQxdQ0/XM5GYYtQE6SzWBtkEqDhARZg2dvcj1xs/s.swf</div><div></div><div>足球规则第三章 队员人数</div><div>http://you.video.sina.com.cn/api/sinawebApi/outplayrefer.php/vid=10939528_1279208024_a0u1GnZuDGHK+l1lHz2stqkP7KQNt6nki229uVKsJQxdQ0/XM5GYYtQE6SzUCNkEqDhARZg2dvcj1RU/s.swf</div><div></div><div>足球规则第四章 队员装备</div><div>http://you.video.sina.com.cn/api/sinawebApi/outplayrefer.php/vid=10939735_1279208024_OEjjSyA/XmDK+l1lHz2stqkP7KQNt6nki229uVKsJQxdQ0/XM5GYYtQE6S7VBdkEqDhARZg2dvch1Bg/s.swf</div><div></div><div>足球规则第五章 裁判员</div><div>http://you.video.sina.com.cn/api/sinawebApi/outplayrefer.php/vid=10939594_1279208024_aEmyGHZuB2TK+l1lHz2stqkP7KQNt6nki229uVKsJQxdQ0/XM5GYYtQE6SzfBNkEqDhARZg2dvcj3hk/s.swf</div><div></div><div>足球规则第六章 助理裁判员</div><div>http://you.video.sina.com.cn/api/sinawebApi/outplayrefer.php/vid=10939656_1279208024_aBm8SHNrDWXK+l1lHz2stqkP7KQNt6nki229uVKsJQxdQ0/XM5GYYtQE6S/TBtkEqDhARZg2dvcg0hs/s.swf</div><div></div><div>足球规则第七章 比赛时间</div><div>http://you.video.sina.com.cn/api/sinawebApi/outplayrefer.php/vid=10939865_1279208024_bkO8GiE8XmHK+l1lHz2stqkP7KQNt6nki229uVKsJQxdQ0/XM5GYYtQE6SHQBdkEqDhARZg2dvcu0Rg/s.swf</div><div></div><div>足球规则第八章 比赛开始及重新开始</div><div>http://you.video.sina.com.cn/api/sinawebApi/outplayrefer.php/vid=10939728_1279208024_aB3gRyQ6Xm7K+l1lHz2stqkP7KQNt6nki229uVKsJQxdQ0/XM5GYYtQE6S7UCNkEqDhARZg2dvch1RU/s.swf</div><div></div><div>足球规则第九章 比赛进行及死球</div><div>http://you.video.sina.com.cn/api/sinawebApi/outplayrefer.php/vid=10939750_1279208024_bhm0SyNpXWfK+l1lHz2stqkP7KQNt6nki229uVKsJQxdQ0/XM5GYYtQE6S7TANkEqDhARZg2dvch0h0/s.swf</div><div></div><div>足球规则第十章 记胜方法</div><div>http://you.video.sina.com.cn/api/sinawebApi/outplayrefer.php/vid=10939969_1279208024_Zx7kSCo+XW/K+l1lHz2stqkP7KQNt6nki229uVKsJQxdQ0/XM5GYYtQE6SDQCdkEqDhARZg2dvcv0RQ/s.swf</div><div></div><div>足球规则第十一章 越位</div><div>http://you.video.sina.com.cn/api/sinawebApi/outplayrefer.php/vid=10940141_1279208024_O0mxHXFqCm7K+l1lHz2stqkP7KQNt6nki229uVKsJQxdQ0/XM5GYYtQD4CjSAdkEqDhARZg2cf4n0xw/s.swf</div><div></div><div>足球规则第十二章 犯规与不正当行为</div><div>http://you.video.sina.com.cn/api/sinawebApi/outplayrefer.php/vid=10940156_1279208024_bh/nTSNuDG7K+l1lHz2stqkP7KQNt6nki229uVKsJQxdQ0/XM5GYYtQD4CjTBtkEqDhARZg2cf4n0hs/s.swf</div><div></div><div>足球规则第十三章 任意球</div><div>http://you.video.sina.com.cn/api/sinawebApi/outplayrefer.php/vid=25544688_1279208024_O0m0TCo4XmPK+l1lHz2stqkP7KQNt6nki229uVKsJQxdQ0/XM5GbZ9gD5C/eCNkEqDhARp06cfog3xU/s.swf</div><div></div><div>足球规则第十四章 罚球点球</div><div>http://you.video.sina.com.cn/api/sinawebApi/outplayrefer.php/vid=25544796_1279208024_bUvmTCMxBmXK+l1lHz2stqkP7KQNt6nki229uVKsJQxdQ0/XM5GbZ9gD5C7fBtkEqDhARp06cfoh3hs/s.swf</div><div></div><div>足球规则第十五章 掷界外球</div><div>http://you.video.sina.com.cn/api/sinawebApi/outplayrefer.php/vid=25544834_1279208024_a028GiI4CjXK+l1lHz2stqkP7KQNt6nki229uVKsJQxdQ0/XM5GbZ9gD5CHVBNkEqDhARp06cfou1Bk/s.swf</div><div></div><div>足球规则第十六章 球门球</div><div>http://you.video.sina.com.cn/api/sinawebApi/outplayrefer.php/vid=25536623_1279208024_P021SSQxC2bK+l1lHz2stqkP7KQNt6nki229uVKsJQxdQ0/XM5GbZ9gE5i/UA9kEqDhARp06dvgg1R4/s.swf</div><div></div><div>足球规则第十七章 角球</div><div>http://you.video.sina.com.cn/api/sinawebApi/outplayrefer.php/vid=25544954_1279208024_bErmTis6CzPK+l1lHz2stqkP7KQNt6nki229uVKsJQxdQ0/XM5GbZ9gD5CDTBNkEqDhARp06cfov0hk/s.swf</div><img src ="http://www.blogjava.net/weiwei/aggbug/407865.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weiwei/" target="_blank">liwei5891</a> 2013-12-21 23:41 <a href="http://www.blogjava.net/weiwei/articles/407865.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>海量用户积分排名算法探讨(转)</title><link>http://www.blogjava.net/weiwei/articles/406768.html</link><dc:creator>liwei5891</dc:creator><author>liwei5891</author><pubDate>Mon, 25 Nov 2013 00:37:00 GMT</pubDate><guid>http://www.blogjava.net/weiwei/articles/406768.html</guid><wfw:comment>http://www.blogjava.net/weiwei/comments/406768.html</wfw:comment><comments>http://www.blogjava.net/weiwei/articles/406768.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/weiwei/comments/commentRss/406768.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weiwei/services/trackbacks/406768.html</trackback:ping><description><![CDATA[<h3><span style="font-weight: normal;">转至：</span><a href="http://www.cnblogs.com/weidagang2046/archive/2012/03/01/massive-user-ranking.html"><span style="font-weight: normal;">http://www.cnblogs.com/weidagang2046/archive/2012/03/01/massive-user-ranking.html<br /></span></a><br />问题</h3><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">某海量用户网站，用户拥有积分，积分可能会在使用过程中随时更新。现在要为该网站设计一种算法，在每次用户登录时显示其当前积分排名。用户最大规模为2亿；积分为非负整数，且小于100万。</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">PS: 据说这是迅雷的一道面试题，不过问题本身具有很强的真实性，所以本文打算按照真实场景来考虑，而不局限于面试题的理想环境。</p><h3>存储结构</h3><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">首先，我们用一张用户积分表user_score来保存用户的积分信息。</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">表结构：</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;"><img src="http://images.cnblogs.com/cnblogs_com/weidagang2046/359580/r_user_score_schema.png" alt="user&lt;em /&gt;score&lt;/em&gt;schema" title="" style="border: 0px;" /></p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">示例数据：</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;"><img src="http://images.cnblogs.com/cnblogs_com/weidagang2046/359580/r_user_score_sample.png" alt="user&lt;em /&gt;score&lt;/em&gt;sample" title="" style="border: 0px;" /></p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">下面的算法会基于这个基本的表结构来进行。</p><h3>算法1：简单SQL查询</h3><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">首先，我们很容易想到用一条简单的SQL语句查询出积分大于该用户积分的用户数量：</p><pre style="margin-top: 10px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; color: #535353; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;"><code style="padding-top: 5px; color: #800040;">select 1 + count(t2.uid) as rank from user_score t1, user_score t2 where t1.uid = @uid and t2.score &gt; t1.score </code></pre><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">对于4号用户我们可以得到下面的结果：</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;"><img src="http://images.cnblogs.com/cnblogs_com/weidagang2046/359580/o_sql.png" alt="sql_1" title="" style="border: 0px;" /></p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">算法特点</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">优点：简单，利用了SQL的功能，不需要复杂的查询逻辑，也不引入额外的存储结构，对小规模或性能要求不高的应用不失为一种良好的解决方案。</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">缺点：需要对user_score表进行全表扫描，还需要考虑到查询的同时若有积分更新会对表造成锁定，在海量数据规模和高并发的应用中，性能是无法接受的。</p><h3>算法2：均匀分区设计</h3><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">在许多应用中缓存是解决性能问题的重要途径，我们自然会想能不能把用户排名用Memcached缓存下来呢？不过再一想发现缓存似乎帮不上什么忙，因为用户排名是一个全局性的统计性指标，而并非用户的私有属性，其他用户的积分变化可能会马上影响到本用户的排名。然而，真实的应用中积分的变化其实也是有一定规律的，通常一个用户的积分不会突然暴增暴减，一般用户总是要在低分区混迹很长一段时间才会慢慢升入高分区，也就是说用户积分的分布总体说来是有区段的，我们进一步注意到高分区用户积分的细微变化其实对低分段用户的排名影响不大。于是，我们可以想到按积分区段进行统计的方法，引入一张分区积分表score_range：</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">表结构：</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;"><img src="http://images.cnblogs.com/cnblogs_com/weidagang2046/359580/r_score_range_schema.png" alt="score&lt;em /&gt;range&lt;/em&gt;schema" title="" style="border: 0px;" /></p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">数据示例：</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;"><img src="http://images.cnblogs.com/cnblogs_com/weidagang2046/359580/r_score_range_sample.png" alt="score&lt;em /&gt;range&lt;/em&gt;sample" title="" style="border: 0px;" /></p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">表示[from_score, to_score)区间有count个用户。若我们按每1000分划分一个区间则有[0, 1000), [1000, 2000), &#8230;, [999000, 1000000)这1000个区间，以后对用户积分的更新要相应地更新score_range表的区间值。在分区积分表的辅助下查询积分为s的用户的排名，可以首先确定其所属区间，把高于s的积分区间的count值累加，然后再查询出该用户在本区间内的排名，二者相加即可获得用户的排名。</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">乍一看，这个方法貌似通过区间聚合减少了查询计算量，实则不然。最大的问题在于如何查询用户在本区间内的排名呢？如果是在算法1中的SQL中加上积分条件：</p><pre style="margin-top: 10px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word; color: #535353; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;"><code style="padding-top: 5px; color: #800040;">select 1 + count(t2.uid) as rank from user_score t1, user_score t2 where t1.uid = @uid and t2.score &gt; t1.score and t2.score &lt; @to_score </code></pre><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">在理想情况下，由于把t2.score的范围限制在了1000以内，如果对score字段建立索引，我们期望本条SQL语句将通过索引大大减少扫描的user_score表的行数。不过真实情况并非如此，t2.score的范围在1000以内并不意味着该区间内的用户数也是1000，因为这里有积分相同的情况存在！二八定律告诉我们，前20%的低分区往往集中了80%的用户，这就是说对于大量低分区用户进行区间内排名查询的性能远不及对少数的高分区用户，所以在一般情况下这种分区方法不会带来实质性的性能提升。</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">算法特点</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">优点：注意到了积分区间的存在，并通过预先聚合消除查询的全表扫描。</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">缺点：积分非均匀分布的特点使得性能提升并不理想。</p><h3>算法3：树形分区设计</h3><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">均匀分区查询算法的失败是由于积分分布的非均匀性，那么我们自然就会想，能不能按二八定律，把score_range表设计为非均匀区间呢？比如，把低分区划密集一点，10分一个区间，然后逐渐变成100分，1000分，10000分 &#8230; 当然，这不失为一种方法，不过这种分法有一定的随意性，不容易把握好，而且整个系统的积分分布会随着使用而逐渐发生变化，最初的较好的分区方法可能会变得不适应未来的情况了。我们希望找到一种分区方法，既可以适应积分非均匀性，又可以适应系统积分分布的变化，这就是树形分区。</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">我们可以把[0, 1,000,000)作为一级区间；再把一级区间分为两个2级区间[0, 500,000), [500,000, 1,000,000)，然后把二级区间二分为4个3级区间[0, 250,000), [250,000, 500,000), [500,000, 750,000), [750,000, 1,000,000)，依此类推，最终我们会得到1,000,000个21级区间[0,1), [1,2) &#8230; [999,999, 1,000,000)。这实际上是把区间组织成了一种平衡二叉树结构，根结点代表一级区间，每个非叶子结点有两个子结点，左子结点代表低分区间，右子结点代表高分区间。树形分区结构需要在更新时保持一种不变量(Invariant)：非叶子结点的count值总是等于其左右子结点的count值之和。</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;"><img src="http://images.cnblogs.com/cnblogs_com/weidagang2046/359580/r_ranking_tree.png" alt="range_tree" title="" style="border: 0px;" /></p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">以后，每次用户积分有变化所需要更新的区间数量和积分变化量有关系，积分变化越小更新的区间层次越低。总体上，每次所需要更新的区间数量是用户积分变量的log(n)级别的，也就是说如果用户积分一次变化在百万级，更新区间的数量在二十这个级别。在这种树形分区积分表的辅助下查询积分为s的用户排名，实际上是一个在区间树上由上至下、由粗到细一步步明确s所在位置的过程。比如，对于积分499,000，我们用一个初值为0的排名变量来做累加；首先，它属于1级区间的左子树[0, 500,000)，那么该用户排名应该在右子树[500,000, 1,000,000)的用户数count之后，我们把该count值累加到该用户排名变量，进入下一级区间；其次，它属于3级区间的[250,000, 500,000)，这是2级区间的右子树，所以不用累加count到排名变量，直接进入下一级区间；再次，它属于4级区间的&#8230;；直到最后我们把用户积分精确定位在21级区间[499,000, 499,001)，整个累加过程完成，得出排名！</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">虽然，本算法的更新和查询都涉及到若干个操作，但如果我们为区间的from_score和to_score建立索引，这些操作都是基于键的查询和更新，不会产生表扫描，因此效率更高。另外，本算法并不依赖于关系数据模型和SQL运算，可以轻易地改造为NoSQL等其他存储方式，而基于键的操作也很容易引入缓存机制进一步优化性能。进一步，我们可以估算一下树形区间的数目大约为2,000,000，考虑每个结点的大小，整个结构只占用几十M空间。所以，我们完全可以在内存建立区间树结构，并通过user_score表在O(n)的时间内初始化区间树，然后排名的查询和更新操作都可以在内存进行。一般来讲，同样的算法，从数据库到内存算法的性能提升常常可以达到10^5以上；因此，本算法可以达到非常高的性能。</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">算法特点</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">优点：结构稳定，不受积分分布影响；每次查询或更新的复杂度为积分最大值的O(log(n))级别，且与用户规模无关，可以应对海量规模；不依赖于SQL，容易改造为NoSQL或内存数据结构。</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">缺点：算法相对更复杂。</p><h3>算法4：积分排名数组</h3><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">算法3虽然性能较高，达到了积分变化的O(log(n))的复杂度，但是实现上比较复杂。另外，O(log(n))的复杂度只在n特别大的时候才显出它的优势，而实际应用中积分的变化情况往往不会太大，这时和O(n)的算法相比往往没有明显的优势，甚至可能更慢。</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">考虑到这一情况，仔细观察一下积分变化对排名的具体影响，可以发现某用户的积分从s变为s+n，积分小于s或者大于等于s+n的其他用户排名实际上并不会受到影响，只有积分在[s,s+n)区间内的用户排名会下降1位。我们可以用于一个大小为1,000,000的数组表示积分和排名的对应关系，其中rank[s]表示积分s所对应的排名。初始化时，rank数组可以由user_score表在O(n)的复杂度内计算而来。用户排名的查询和更新基于这个数组来进行。查询积分s所对应的排名直接返回rank[s]即可，复杂度为O(1)；当用户积分从s变为s+n，只需要把rank[s]到rank[s+n-1]这n个元素的值增加1即可，复杂度为O(n)。</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">算法特点</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">优点：积分排名数组比区间树更简单，易于实现；排名查询复杂度为O(1)；排名更新复杂度O(n)，在积分变化不大的情况下非常高效。</p><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">缺点：当n比较大时，需要更新大量元素，效率不如算法3。</p><h3>总结</h3><p style="-webkit-margin-before: 0px; -webkit-margin-after: 0px; margin-top: 10px; margin-bottom: 10px; color: #535353; font-family: Quicksand, 'Helvetica Neue', sans-serif; font-size: 15.555556297302246px; line-height: 23.99305534362793px; background-color: #ffffff;">上面介绍了用户积分排名的几种算法，算法1简单易于理解和实现，适用于小规模和低并发应用；算法3引入了更复杂的树形分区结构，但是O(log(n))的复杂度性能优越，可以应用于海量规模和高并发；算法4采用简单的排名数组，易于实现，在积分变化不大的情况下性能不亚于算法3。本问题是一个开放性的问题，相信一定还有其他优秀的算法和解决方案，欢迎探讨！</p><img src ="http://www.blogjava.net/weiwei/aggbug/406768.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weiwei/" target="_blank">liwei5891</a> 2013-11-25 08:37 <a href="http://www.blogjava.net/weiwei/articles/406768.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>PowerDesigner CDM datatype 在图中显示为简写</title><link>http://www.blogjava.net/weiwei/articles/405035.html</link><dc:creator>liwei5891</dc:creator><author>liwei5891</author><pubDate>Wed, 16 Oct 2013 01:03:00 GMT</pubDate><guid>http://www.blogjava.net/weiwei/articles/405035.html</guid><wfw:comment>http://www.blogjava.net/weiwei/comments/405035.html</wfw:comment><comments>http://www.blogjava.net/weiwei/articles/405035.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weiwei/comments/commentRss/405035.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weiwei/services/trackbacks/405035.html</trackback:ping><description><![CDATA[<span style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">Tools-&gt;</span>Model Settings -&gt; Domain/Attribute -&gt;Use data type full name<img src ="http://www.blogjava.net/weiwei/aggbug/405035.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weiwei/" target="_blank">liwei5891</a> 2013-10-16 09:03 <a href="http://www.blogjava.net/weiwei/articles/405035.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA垃圾回收</title><link>http://www.blogjava.net/weiwei/articles/404814.html</link><dc:creator>liwei5891</dc:creator><author>liwei5891</author><pubDate>Wed, 09 Oct 2013 13:35:00 GMT</pubDate><guid>http://www.blogjava.net/weiwei/articles/404814.html</guid><wfw:comment>http://www.blogjava.net/weiwei/comments/404814.html</wfw:comment><comments>http://www.blogjava.net/weiwei/articles/404814.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weiwei/comments/commentRss/404814.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weiwei/services/trackbacks/404814.html</trackback:ping><description><![CDATA[<div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">哪些内存需要回收？</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">什么时候回收？</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">如何回收？</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">一：哪些内存需要回收？</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">JAVA内存中不需要考虑内存回收问题的区域：</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">程序计数器、虚拟机栈，本地方法栈</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">（随线程生灭，栈帧分配多少内存在类结构确定是就已知，因此它们的内存分配与回收具备确定性。方法结束或线程结束时，内存自然就跟着回收了）</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">需要考虑内存回收问题的区域：</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">JAVA堆和方法区</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">(创建哪些对象，创建多少对象，需要在运行期间才知道。不再用创建对象的类定义要从方法区回收)</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">二：堆中对象的回收</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">死去的对象才会被回收</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">如何判断对象已死</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">a.引用计数算法：</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">给对象添加一个引用计数器，每当有一个地方引用它时，计数器值就加1。引用失效时，计数器值就减1.任何时候计数器为0的对象就是不可能再被使用的。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">优点：引用计数算法实现简单，判定效率也高。(使用在COM,FlashPlayer,Python等语言中)</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">缺点：它很难解决对象之间相互循环引用的问题。（因此JAVA中没有选用它来管理内存）</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">b.根搜索算法</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">对于任何"GC Roots"都没有路径到达对象时，该对象就是不可用的。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">主流的程序语言都用的是根搜索算法，包括JAVA语言。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">哪些对象才是"GC　Roots"</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"><ul style="margin: 0.2857em 0px 0.714285em 2em; padding: 0px; border: 0px; line-height: 1.428571em; list-style-position: outside;"><li style="margin: 0px; padding: 0px; border: 0px; line-height: 1.428571em;">虚拟机栈(栈帧中的本地变量表)中引用的对象</li><li style="margin: 0px; padding: 0px; border: 0px; line-height: 1.428571em;">方法区中的类静态属性引用的对象</li><li style="margin: 0px; padding: 0px; border: 0px; line-height: 1.428571em;">方法区中的常量引用的对象</li><li style="margin: 0px; padding: 0px; border: 0px; line-height: 1.428571em;">本地方法栈中JNI的引用的对象</li></ul><div style="margin: 0px; border: 0px; line-height: 1.428571em;">JAVA中的引用分为：强引用（Strong Reference）、软引用（Soft Reference）、弱引用（Weak Reference）、虚引用（Phantom Reference）四种，强度依次减弱</div></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"><ul style="margin: 0.2857em 0px 0.714285em 2em; padding: 0px; border: 0px; line-height: 1.428571em; list-style-position: outside;"><li style="margin: 0px; padding: 0px; border: 0px; line-height: 1.428571em;">强引用：代码中存在，类似 "Object obj = new Object()"这类。只要强引用存在，GC就永远不会回收掉被引用的对象。</li><li style="margin: 0px; padding: 0px; border: 0px; line-height: 1.428571em;">软引用：描述一些还有用，但非必需的对象。在系统将要发生内存溢出异常之前，将把这些对象列进回范围之中并进行第二次回收。如果这次回收还没有足够的内存，才会抛出内存溢出异常。通过 SoftReference类来实现软引用。</li><li style="margin: 0px; padding: 0px; border: 0px; line-height: 1.428571em;">弱引用：也用于描述非必需对象，但它的强度要比软引用更弱一些，被弱引用关联的对象只能生成到下一次GC发生之前。当GC工作时，无论当前内存是否足够，都会回收弱引用关联的对象。通过 WeakReference类来实现弱引用</li><li style="margin: 0px; padding: 0px; border: 0px; line-height: 1.428571em;">虚引用：也称为幽灵引用或幻影引用。设置虚引用关联的唯一目录就是希望这个对象被回收时收到一个系统通知。通过PhantomReference来实现虚引用</li></ul></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">究竟什么样的对象才会死掉呢？</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">要真正宣告一个对象死亡，<strong style="line-height: 1.428571em;">至少要经历两次标记过程</strong>：如果对象在进行根搜索后发现没有与 GC Roots 相连接的引用链，那它将会被第一次标记并放到&#8220;即将被回收的集合&#8221;中。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">与此同时进行一次筛选，筛选的条件是此对象是否有必要执行 finalize() 方法。(当对象没有覆盖 finalize()方法，或者 finalize() 方法已经被虚拟机调用过，虚拟机将这两种情况都视为 "没有必要执行"。)如果这个对象被判定为有必要执行 finalize()方法，那么这个对象将会被放置到一个名为 F-Queue 的队列之中，将在稍后由一条由虚拟机自动建立的，低优先级的 Finalizer 线程去执行（触发finalize()方法而不等待）。finalize()方法是对象逃脱死亡命运的最后一次机会。对象要在finalize()方法中拯救自己，只要重新与引用链上任何一个对象建立关联即可，这样的话第二次标记时它被移除出&#8220;即将回收的集合&#8221;。如果对象这个时候还没有逃脱，那就真的离死不远了。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">三：方法区的回收</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">主要回收两部份内容：废弃常量、无用的类</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">常量回收与堆中对象回收类似。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">无用的类的判断需同时满足3条：</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"><ul style="margin: 0.2857em 0px 0.714285em 2em; padding: 0px; border: 0px; line-height: 1.428571em; list-style-position: outside;"><li style="margin: 0px; padding: 0px; border: 0px; line-height: 1.428571em;">该类所有的实例都已经被回收，也就是说堆中不存在该类的任何实例</li><li style="margin: 0px; padding: 0px; border: 0px; line-height: 1.428571em;">加载该类的 ClassLoader 已经被回收</li><li style="margin: 0px; padding: 0px; border: 0px; line-height: 1.428571em;">该类对应的 java.lang.Class 对象没有在任何地方被引用，无法在任何地方通过反射访问该类的方法</li></ul></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">虚拟机对满足上述3个条件的无用类进行回收。（只是可以，不会是必然回收）是否对类进行回收，HotSpot虚拟机了 -Xnoclassgc参数进行控制。还可以使用 -verbose:class 及-XX:+TraceClassLoading 和 -XX:+TraceClassUnLoading查看类的加载和卸载信息。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">四：垃圾收集算法</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">4.1 标记-清除算法</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">标记出所有需要回收的对象，标记完成后统一回收掉所有被标记的对象。（如何标记在堆对象回收部分有介绍）</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">它是最基础的收集算法，后续收集算法都是基于这种思路改进而得到。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">缺点：效率不高，产生大量不连续的内存碎片。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">（空间碎片太多，分配较大对象时就无法找到足够连续内存空间，而不得不提前触发另一次垃圾收集动作）</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">4.2 复制算法</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">（为解决效率问题）</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">将内存按容量划分为大小相等的两块，每次只使用其中的一块。当这一块内存用完了，就将还存活着的对象复制到另一块上面，然后再把已使用过的内存空间一次清理掉。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">优点：内存分配时不用考虑碎片的问题，实现简单，运行高效</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">缺点：内存缩小为原来的一半。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">当对象存活率较高时，需要较多的复制操作，效率将会变低。若不想浪费50%的空间，需要额外的空间进行分配担保</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">现在的商业虚拟机都采用这种收集算法来回收新生代(IBM研究表明，新生代对象98%是朝夕死的)。不过，并不是按1：1的比例来划分内存空间。而是将内存分为一块较大的 Eden 空间 和两块较小的Survivor空间。每次只使用 Eden 和其中的一块Survivor。当回收时，将Eden和Survivor中还存活着的对象一次性拷贝到另外一块Survivor空间上，最后清理掉刚才的Eden和Survivor。默认Eden和Survivor比例是 8:1。（98%是一般场景，另外一些场景下，当Survivor空间不够时，需依赖其它内存【老年代】进行分配担保）</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">4.3 标记-整理算法</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">复制算法的缺点，决定老年代不能使用复制算法</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">根据老年代特点，提出了&#8220;标记-整理算法&#8221;。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">标记过程仍然与&#8220;标记-清除&#8221;算法一样，但后续步骤不是直接对可回收对象进行清理，而是让所有存活的对象都向一端移动，然后直接清理掉端边界以外的内存。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">4.4 分代收集算法</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">当前虚拟机的垃圾收集都采用&#8220;分代收集&#8221;算法。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">根据对象的存活周期将内存划分为几块。一般将堆分为新生代和老年代，这样根据各个年代的特点采用最适当的收集算法。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">新生代采用复制算法</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">老年代采用&#8220;标记-清理&#8221;或&#8220;标记-整理&#8221;算法</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">五：垃圾收集器</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">算法是内存回收的方法论，垃圾收集器是内存回收的具体实现。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"><img src="https://app.yinxiang.com/shard/s4/res/ef7b3d87-efb5-4410-9d09-c6ab86c98857.png?resizeSmall&amp;width=700" alt="" name="ef7b3d87-efb5-4410-9d09-c6ab86c98857" data-mce-src="https://app.yinxiang.com/shard/s4/res/ef7b3d87-efb5-4410-9d09-c6ab86c98857.png?resizeSmall&amp;width=700" data-mce-style="cursor: default;" style="margin: 0.857412em 0px 0px; padding: 0px; border: 0px; cursor: default;" /></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">Serial收集器</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">缺点：单线程收集器，垃圾收集时必须暂停其它所有的工作线程（Stop the world）。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">优点：简单而高效，对于Client模式下的虚拟机来说是一个很好的选择。（也是Client模式下的默认新生代收集器）</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">ParNew 收集器</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">其实就是 Serial 收集器的多线程版本</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">是Server模式下的虚拟机的首选新生代收集器。（一个重要原因是，目前除了Serial收集器外，只有它能与CMS收集器配合工作）</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">Paraller Scavenge 收集器</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">并行的多线程收集器</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">它的关注点与其它收集器的不同，它关注的是吞吐量</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">吞吐量=运行用户代码时间/(运用用户代码时间+垃圾收集时间)</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">Serial Old 收集器</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">是Serial收集器的老年代版本，同样是单线程收集器。使用&#8220;标记-整理&#8221;算法</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">Parallel Old 收集器</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">是Parallel Scavenge收集器的老年代版本，使用多线和和&#8220;标记-整理算法&#8221;，JDK1.6才提供。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">注重吞吐量及CPU资源敏感的场合，可以优先考虑Parallel Scavenge加Parallel Old组合。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">CMS收集器 （Concurrent Mark Sweep）</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">是一种以获取最短回收停顿时间为目标的收集器。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">对于B/S类重视服务器响应速度，希望停顿时间最短类应用就比较适合。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">基于&#8220;标记-清除算法实现&#8221;</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">内存回收过程与用户线程起并发的执行。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">缺点：</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">对CPU资源非常敏感。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">无法处理浮动垃圾</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">收集结束时会产生大量空间碎片</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">G1收集器（Garbage First）`</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">JDK1.7正式发布时，很可能会有一个成熟的商业版本随之发布。</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">相对CMS的改进：</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">基于&#8220;标记-整理&#8221;算法实现，不会产生空间碎片</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">可以非常精确的控制停顿</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;">可以实现基本不牺牲吞吐量的前提下完成低停顿的内存回收</div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><div style="margin: 0px; border: 0px; line-height: 1.428571em; font-family: Helvetica, Arial, 'Droid Sans', sans-serif;"></div><img src ="http://www.blogjava.net/weiwei/aggbug/404814.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weiwei/" target="_blank">liwei5891</a> 2013-10-09 21:35 <a href="http://www.blogjava.net/weiwei/articles/404814.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>