﻿<?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-MikeChen专注电子商务-随笔分类-高级</title><link>http://www.blogjava.net/mikechen/category/50933.html</link><description>电子商务技术架构</description><language>zh-cn</language><lastBuildDate>Thu, 20 Jun 2013 08:36:16 GMT</lastBuildDate><pubDate>Thu, 20 Jun 2013 08:36:16 GMT</pubDate><ttl>60</ttl><item><title>java classLoader 体系结构</title><link>http://www.blogjava.net/mikechen/archive/2013/06/20/400762.html</link><dc:creator>陈睿</dc:creator><author>陈睿</author><pubDate>Thu, 20 Jun 2013 02:25:00 GMT</pubDate><guid>http://www.blogjava.net/mikechen/archive/2013/06/20/400762.html</guid><wfw:comment>http://www.blogjava.net/mikechen/comments/400762.html</wfw:comment><comments>http://www.blogjava.net/mikechen/archive/2013/06/20/400762.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mikechen/comments/commentRss/400762.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mikechen/services/trackbacks/400762.html</trackback:ping><description><![CDATA[<div style="margin-bottom: 10px; overflow: auto; zoom: 1; padding-left: 1px; padding-right: 1px; padding-bottom: 1px; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #cccccc; font-family: Tahoma, Helvetica, Arial, 宋体, sans-serif; font-size: 13px; line-height: normal;"><span style="float: left;"><br /></span></div><div post="" hentry="" category-java="" tag-architecture=""  tag-classloader"="" id="post-1060" style="margin-bottom: 20px; overflow: auto; zoom: 1; padding-bottom: 10px; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #cccccc; font-family: Tahoma, Helvetica, Arial, 宋体, sans-serif; font-size: 13px; line-height: normal;"><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;"><a href="http://creativecommons.org/licenses/by/3.0/deed.zh" rel="bookmark" style="text-decoration: none; color: #0044aa;">版权信息</a>: 可以任意转载, 转载时请务必以超链接形式标明文章<strong>原文出处</strong>, 即下面的声明.</p><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;"></p><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;">原文出处：<a href="http://blog.chenlb.com/2009/06/java-classloader-architecture.html" style="text-decoration: none; color: #0044aa;">http://blog.chenlb.com/2009/06/java-classloader-architecture.html</a></p><div style="width: 692px;"><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;"><strong>jvm classLoader architecture：</strong></p><ol style="margin: 0px 0px 15px; padding: 0px; list-style-position: initial; list-style-image: initial;"><li style="margin: 0px; padding: 0px; line-height: 20px;">Bootstrap ClassLoader/启动类加载器&nbsp;<br />主要负责jdk_home/lib目录下的核心 api 或 -Xbootclasspath 选项指定的jar包装入工作。</li><li style="margin: 0px; padding: 0px; line-height: 20px;">Extension ClassLoader/扩展类加载器&nbsp;<br />主要负责jdk_home/lib/ext目录下的jar包或 -Djava.ext.dirs 指定目录下的jar包装入工作。</li><li style="margin: 0px; padding: 0px; line-height: 20px;">System ClassLoader/系统类加载器&nbsp;<br />主要负责java -classpath/-Djava.class.path所指的目录下的类与jar包装入工作。</li><li style="margin: 0px; padding: 0px; line-height: 20px;">User Custom ClassLoader/用户自定义类加载器(java.lang.ClassLoader的子类)&nbsp;<br />在程序运行期间, 通过java.lang.ClassLoader的子类动态加载class文件, 体现java动态实时类装入特性。</li></ol><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;"><strong>类加载器的特性：</strong></p><ol style="margin: 0px 0px 15px; padding: 0px; list-style-position: initial; list-style-image: initial;"><li style="margin: 0px; padding: 0px; line-height: 20px;">每个ClassLoader都维护了一份自己的名称空间， 同一个名称空间里不能出现两个同名的类。</li><li style="margin: 0px; padding: 0px; line-height: 20px;">为了实现java安全沙箱模型顶层的类加载器安全机制, java默认采用了 " 双亲委派的加载链 " 结构。</li></ol><div id="attachment_1066"  alignnone"="" style="border: 1px solid #dddddd; text-align: center; background-color: #f3f3f3; padding-top: 4px; margin: 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; width: 177px;"><img wp-image-1066=""  "="" title="classloader-architecture" src="http://blog.chenlb.com/wp-content/uploads/2009/06/classloader-architecture.jpg" alt="classloader-architecture" width="167" height="281" style="border: 0px none; max-width: 600px; margin: 0px; padding: 0px;" /><p style="margin: 0px; padding: 0px 4px 5px; line-height: 17px; font-size: 11px;">classloader-architecture</p></div><div id="attachment_1067"  alignnone"="" style="border: 1px solid #dddddd; text-align: center; background-color: #f3f3f3; padding-top: 4px; margin: 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; width: 353px;"><img wp-image-1067=""  "="" title="classloader-class-diagram" src="http://blog.chenlb.com/wp-content/uploads/2009/06/classloader-class-diagram.jpg" alt="classloader-class-diagram" width="343" height="465" style="border: 0px none; max-width: 600px; margin: 0px; padding: 0px;" /><p style="margin: 0px; padding: 0px 4px 5px; line-height: 17px; font-size: 11px;">classloader-class-diagram</p></div><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;">类图中， BootstrapClassLoader是一个单独的java类， 其实在这里， 不应该叫他是一个java类。因为，它已经完全不用java实现了。它是在jvm启动时， 就被构造起来的， 负责java平台核心库。</p><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;"><strong>自定义类加载器加载一个类的步骤</strong></p><div id="attachment_1068"  alignnone"="" style="border: 1px solid #dddddd; text-align: center; background-color: #f3f3f3; padding-top: 4px; margin: 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; width: 593px;"><img wp-image-1068=""  "="" title="classloader-load-class" src="http://blog.chenlb.com/wp-content/uploads/2009/06/classloader-load-class.jpg" alt="classloader-load-class" width="583" height="289" style="border: 0px none; max-width: 600px; margin: 0px; padding: 0px;" /><p style="margin: 0px; padding: 0px 4px 5px; line-height: 17px; font-size: 11px;">classloader-load-class</p></div><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;"><strong>ClassLoader 类加载逻辑分析， 以下逻辑是除 BootstrapClassLoader 外的类加载器加载流程：</strong></p><div style="font-family: 'Courier New', Courier, mono; width: 671.234375px; margin-left: 9px; padding-right: 1px; padding-bottom: 1px; padding-left: 1px; word-break: break-all; word-wrap: break-word;"><div></div><ol start="1" style="margin-bottom: 15px; margin-left: 0px; padding-top: 2px; padding-bottom: 2px; border: 1px solid #d1d7dc; color: #2b91af;"><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">//&nbsp;检查类是否已被装载过&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">Class&nbsp;c&nbsp;=&nbsp;findLoadedClass(name);&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;"><span style="color: #7f0055;">if</span>&nbsp;(c&nbsp;==&nbsp;<span style="color: #7f0055;">null</span>&nbsp;)&nbsp;{&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;指定类未被装载过&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7f0055;">try</span>&nbsp;{&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7f0055;">if</span>&nbsp;(parent&nbsp;!=&nbsp;<span style="color: #7f0055;">null</span>&nbsp;)&nbsp;{&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;如果父类加载器不为空，&nbsp;则委派给父类加载&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;=&nbsp;parent.loadClass(name,&nbsp;<span style="color: #7f0055;">false</span>&nbsp;);&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #7f0055;">else</span>&nbsp;{&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;如果父类加载器为空，&nbsp;则委派给启动类加载加载&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;=&nbsp;findBootstrapClass0(name);&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #7f0055;">catch</span>&nbsp;(ClassNotFoundException&nbsp;e)&nbsp;{&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;启动类加载器或父类加载器抛出异常后，&nbsp;当前类加载器将其&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;捕获，&nbsp;并通过findClass方法，&nbsp;由自身加载&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;=&nbsp;findClass(name);&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">}&nbsp;&nbsp;</li></ol></div><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;"><strong>线程上下文类加载器</strong><br />java默认的线程上下文类加载器是 系统类加载器(AppClassLoader)。</p><div style="font-family: 'Courier New', Courier, mono; width: 671.234375px; margin-left: 9px; padding-right: 1px; padding-bottom: 1px; padding-left: 1px; word-break: break-all; word-wrap: break-word;"><div></div><ol start="1" style="margin-bottom: 15px; margin-left: 0px; padding-top: 2px; padding-bottom: 2px; border: 1px solid #d1d7dc; color: #2b91af;"><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">//&nbsp;Now&nbsp;create&nbsp;the&nbsp;class&nbsp;loader&nbsp;to&nbsp;use&nbsp;to&nbsp;launch&nbsp;the&nbsp;application&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;"><span style="color: #7f0055;">try</span>&nbsp;{&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;loader&nbsp;=&nbsp;AppClassLoader.getAppClassLoader(extcl);&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">}&nbsp;<span style="color: #7f0055;">catch</span>&nbsp;(IOException&nbsp;e)&nbsp;{&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7f0055;">throw</span>&nbsp;<span style="color: #7f0055;">new</span>&nbsp;InternalError(&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">"Could&nbsp;not&nbsp;create&nbsp;application&nbsp;class&nbsp;loader"&nbsp;);&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">}&nbsp;&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">//&nbsp;Also&nbsp;set&nbsp;the&nbsp;context&nbsp;class&nbsp;loader&nbsp;for&nbsp;the&nbsp;primordial&nbsp;thread.&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">Thread.currentThread().setContextClassLoader(loader);&nbsp;&nbsp;</li></ol></div><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;">以上代码摘自sun.misc.Launch的无参构造函数Launch()。</p><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;">使用线程上下文类加载器, 可以在执行线程中, 抛弃双亲委派加载链模式, 使用线程上下文里的类加载器加载类.<br />典型的例子有, 通过线程上下文来加载第三方库jndi实现, 而不依赖于双亲委派.<br />大部分java app服务器(jboss, tomcat..)也是采用contextClassLoader来处理web服务。<br />还有一些采用 hotswap 特性的框架, 也使用了线程上下文类加载器, 比如 seasar (full stack framework in japenese).</p><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;">线程上下文从根本解决了一般应用不能违背双亲委派模式的问题.<br />使java类加载体系显得更灵活.</p><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;">随着多核时代的来临, 相信多线程开发将会越来越多地进入程序员的实际编码过程中. 因此,<br />在编写基础设施时， 通过使用线程上下文来加载类, 应该是一个很好的选择。</p><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;">当然, 好东西都有利弊. 使用线程上下文加载类, 也要注意, 保证多根需要通信的线程间的类加载器应该是同一个,<br />防止因为不同的类加载器, 导致类型转换异常(ClassCastException)。</p><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;"><strong>为什么要使用这种双亲委托模式呢？</strong></p><ol style="margin: 0px 0px 15px; padding: 0px; list-style-position: initial; list-style-image: initial;"><li style="margin: 0px; padding: 0px; line-height: 20px;">因为这样可以避免重复加载，当父亲已经加载了该类的时候，就没有必要子ClassLoader再加载一次。</li><li style="margin: 0px; padding: 0px; line-height: 20px;">考虑到安全因素，我们试想一下，如果不使用这种委托模式，那我们就可以随时使用自定义的String来动态替代java核心api中定义类型，这样会存在非常大的安全隐患，而双亲委托的方式，就可以避免这种情况，因为String已经在启动时被加载，所以用户自定义类是无法加载一个自定义的ClassLoader。</li></ol><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;"><strong>java动态载入class的两种方式：</strong></p><ol style="margin: 0px 0px 15px; padding: 0px; list-style-position: initial; list-style-image: initial;"><li style="margin: 0px; padding: 0px; line-height: 20px;">implicit隐式,即利用实例化才载入的特性来动态载入class</li><li style="margin: 0px; padding: 0px; line-height: 20px;">explicit显式方式,又分两种方式:<ol style="margin: 0px 0px 15px; padding: 0px; list-style-position: initial; list-style-image: initial;"><li style="margin: 0px; padding: 0px;">java.lang.Class的forName()方法</li><li style="margin: 0px; padding: 0px;">java.lang.ClassLoader的loadClass()方法</li></ol></li></ol><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;"><strong>用Class.forName加载类</strong></p><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;">Class.forName使用的是被调用者的类加载器来加载类的。<br />这种特性, 证明了java类加载器中的名称空间是唯一的, 不会相互干扰。<br />即在一般情况下, 保证同一个类中所关联的其他类都是由当前类的类加载器所加载的。</p><div style="font-family: 'Courier New', Courier, mono; width: 671.234375px; margin-left: 9px; padding-right: 1px; padding-bottom: 1px; padding-left: 1px; word-break: break-all; word-wrap: break-word;"><div></div><ol start="1" style="margin-bottom: 15px; margin-left: 0px; padding-top: 2px; padding-bottom: 2px; border: 1px solid #d1d7dc; color: #2b91af;"><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;"><span style="color: #7f0055;">public</span>&nbsp;<span style="color: #7f0055;">static</span>&nbsp;Class&nbsp;forName(String&nbsp;className)&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7f0055;">throws</span>&nbsp;ClassNotFoundException&nbsp;{&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7f0055;">return</span>&nbsp;forName0(className,&nbsp;<span style="color: #7f0055;">true</span>&nbsp;,&nbsp;ClassLoader.getCallerClassLoader());&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">}&nbsp;&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">/**&nbsp;Called&nbsp;after&nbsp;security&nbsp;checks&nbsp;have&nbsp;been&nbsp;made.&nbsp;*/&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;"><span style="color: #7f0055;">private</span>&nbsp;<span style="color: #7f0055;">static</span>&nbsp;<span style="color: #7f0055;">native</span>&nbsp;Class&nbsp;forName0(String&nbsp;name,&nbsp;<span style="color: #7f0055;">boolean</span>&nbsp;initialize,&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">ClassLoader&nbsp;loader)&nbsp;&nbsp;</li><li style="margin-left: 38px; padding-right: 0px; line-height: 18px; border-left-width: 1px; border-left-color: #d1d7dc; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7f0055;">throws</span>&nbsp;ClassNotFoundException;&nbsp;&nbsp;</li></ol></div><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;">上面中 ClassLoader.getCallerClassLoader 就是得到调用当前forName方法的类的类加载器</p><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;"><strong>static块在什么时候执行?</strong></p><ul style="margin: 0px 0px 15px 20px; padding: 0px; list-style-position: inside; list-style-image: initial;"><li style="margin: 0px; padding: 0px; line-height: 20px;">当调用forName(String)载入class时执行,如果调用ClassLoader.loadClass并不会执行.forName(String,false,ClassLoader)时也不会执行.</li><li style="margin: 0px; padding: 0px; line-height: 20px;">如果载入Class时没有执行static块则在第一次实例化时执行.比如new ,Class.newInstance()操作</li><li style="margin: 0px; padding: 0px; line-height: 20px;">static块仅执行一次</li></ul><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;"><strong>各个java类由哪些classLoader加载?</strong></p><ul style="margin: 0px 0px 15px 20px; padding: 0px; list-style-position: inside; list-style-image: initial;"><li style="margin: 0px; padding: 0px; line-height: 20px;">java类可以通过实例.getClass.getClassLoader()得知</li><li style="margin: 0px; padding: 0px; line-height: 20px;">接口由AppClassLoader(System ClassLoader,可以由ClassLoader.getSystemClassLoader()获得实例)载入</li><li style="margin: 0px; padding: 0px; line-height: 20px;">ClassLoader类由bootstrap loader载入</li></ul><p style="margin: 0px 0px 15px; padding: 0px; line-height: 20px;"><strong>NoClassDefFoundError和ClassNotFoundException</strong></p><ul style="margin: 0px 0px 15px 20px; padding: 0px; list-style-position: inside; list-style-image: initial;"><li style="margin: 0px; padding: 0px; line-height: 20px;">NoClassDefFoundError:当java源文件已编译成.class文件,但是ClassLoader在运行期间在其搜寻路径load某个类时,没有找到.class文件则报这个错</li><li style="margin: 0px; padding: 0px; line-height: 20px;">ClassNotFoundException:试图通过一个String变量来创建一个Class类时不成功则抛出这个异常</li></ul></div></div><img src ="http://www.blogjava.net/mikechen/aggbug/400762.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mikechen/" target="_blank">陈睿</a> 2013-06-20 10:25 <a href="http://www.blogjava.net/mikechen/archive/2013/06/20/400762.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>事务</title><link>http://www.blogjava.net/mikechen/archive/2012/06/11/380502.html</link><dc:creator>陈睿</dc:creator><author>陈睿</author><pubDate>Mon, 11 Jun 2012 07:46:00 GMT</pubDate><guid>http://www.blogjava.net/mikechen/archive/2012/06/11/380502.html</guid><wfw:comment>http://www.blogjava.net/mikechen/comments/380502.html</wfw:comment><comments>http://www.blogjava.net/mikechen/archive/2012/06/11/380502.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mikechen/comments/commentRss/380502.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mikechen/services/trackbacks/380502.html</trackback:ping><description><![CDATA[一：事务的概念<br />&nbsp; &nbsp;&nbsp;<span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">事务必须服从ISO/IEC所制定的ACID原则。ACID是原子性（atomicity）、一致性（consistency）、隔离性（isolation）和持久性（durability）的缩写</span>&nbsp;<br /><br />&nbsp; &nbsp;&nbsp;<span style="text-align: left; background-color: #ffffff; "><font face="Helvetica, Tahoma, Arial, sans-serif"><span style="line-height: 25px;">事务的原子性：表示事务执行过程中的任何失败都将导致事务所做的任何修改失效。</span></font><br /><div style="text-align: -webkit-auto; ">&nbsp; &nbsp;&nbsp;<font face="Helvetica, Tahoma, Arial, sans-serif"><span style="line-height: 25px;">一致性表示当事务执行失败时，所有被该事务影响的数据都应该恢复到事务执行前的状态。</span></font></div></span><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">&nbsp; &nbsp; &nbsp;隔离性表示在事务执行过程中对数据的修改，在事务提交之前对其他事务不可见。<br />&nbsp; &nbsp; &nbsp;持久性表示已提交的数据在事务执行失败时，数据的状态都应该正确。&nbsp;</span>&nbsp;<br /><br />二：事务的场景<br />&nbsp; &nbsp; 1.与银行相关的业务，重要的数据，与钱相关的内容不能出任何错。<br />&nbsp; &nbsp; 2.系统内部认为重要的数据，都需要事务的支持，防止重要数据的不一致。<br />&nbsp; &nbsp; 3.具体的业务场景：银行业务，支付业务，交易业务等。<br /><br />三：事务的实现方式<br />&nbsp; &nbsp; 首先说一下事务的类型，主要包含一下三种：JDBC事务，JTA事务，容器事务<br />&nbsp; &nbsp;&nbsp;<span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">1、JDBC事务&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">JDBC 事务是用 Connection 对象控制的。JDBC Connection 接口( java.sql.Connection )提供了两种事务模式：自动提交和手工提交。 java.sql.Connection 提供了以下控制事务的方法：&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">public void setAutoCommit(boolean)&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">public boolean getAutoCommit()&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">public void commit()&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">public void rollback()&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">使用 JDBC 事务界定时，您可以将多个 SQL 语句结合到一个事务中。JDBC 事务的一个缺点是事务的范围局限于一个数据库连接。一个 JDBC 事务不能跨越多个数据库。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">2、JTA(Java Transaction API)事务&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">JTA是一种高层的，与实现无关的，与协议无关的API，应用程序和应用服务器可以使用JTA来访问事务。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">JTA允许应用程序执行分布式事务处理--在两个或多个网络计算机资源上访问并且更新数据，这些数据可以分布在多个数据库上。JDBC驱动程序的JTA支持极大地增强了数据访问能力。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">如果计划用 JTA 界定事务，那么就需要有一个实现 javax.sql.XADataSource 、 javax.sql.XAConnection 和 javax.sql.XAResource 接口的 JDBC 驱动程序。一个实现了这些接口的驱动程序将可以参与 JTA 事务。一个 XADataSource 对象就是一个 XAConnection 对象的工厂。 XAConnection s 是参与 JTA 事务的 JDBC 连接。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">您将需要用应用服务器的管理工具设置 XADataSource 。从应用服务器和 JDBC 驱动程序的文档中可以了解到相关的指导。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">J2EE 应用程序用 JNDI 查询数据源。一旦应用程序找到了数据源对象，它就调用 javax.sql.DataSource.getConnection() 以获得到数据库的连接。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">XA 连接与非 XA 连接不同。一定要记住 XA 连接参与了 JTA 事务。这意味着 XA 连接不支持 JDBC 的自动提交功能。同时，应用程序一定不要对 XA 连接调用 java.sql.Connection.commit() 或者 java.sql.Connection.rollback() 。相反，应用程序应该使用 UserTransaction.begin()、 UserTransaction.commit() 和 serTransaction.rollback() 。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">3、容器事务&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">容器事务主要是J2EE应用服务器提供的，容器事务大多是基于JTA完成，这是一个基于JNDI的，相当复杂的API实现。相对编码实现JTA事务管理，我们可以通过EJB容器提供的容器事务管理机制（CMT）完成同一个功能，这项功能由J2EE应用服务器提供。这使得我们可以简单的指定将哪个方法加入事务，一旦指定，容器将负责事务管理任务。这是我们土建的解决方式，因为通过这种方式我们可以将事务代码排除在逻辑编码之外，同时将所有困难交给J2EE容器去解决。使用EJB CMT的另外一个好处就是程序员无需关心JTA API的编码，不过，理论上我们必须使用EJB。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">四、三种事务差异&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">1、JDBC事务控制的局限性在一个数据库连接内，但是其使用简单。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">2、JTA事务的功能强大，事务可以跨越多个数据库或多个DAO，使用也比较复杂。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">3、容器事务，主要指的是J2EE应用服务器提供的事务管理，局限于EJB应用使用。&nbsp;<br /></span><br /><br />五：详解事务<br />1.首先看一下目前使用最多的spring事务，目前spring配置分为声明式事务和编程式事务。<br />&nbsp; 1）编程式事务<br />&nbsp; &nbsp; &nbsp; &nbsp; 主要是实现接口PlatformTransactionManager<br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<img src="http://www.blogjava.net/images/blogjava_net/mikechen/TransactionTemplate.jpg" width="627" height="521" alt="" /><br />&nbsp; &nbsp; &nbsp;<br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; " />&nbsp; &nbsp; &nbsp; &nbsp; 实现了事务管理的接口有非常多，这里主要讲DataSourceTransactionManager和数据库jdbc相关的事务处理方式<img src ="http://www.blogjava.net/mikechen/aggbug/380502.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mikechen/" target="_blank">陈睿</a> 2012-06-11 15:46 <a href="http://www.blogjava.net/mikechen/archive/2012/06/11/380502.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java虚拟机</title><link>http://www.blogjava.net/mikechen/archive/2012/02/27/370847.html</link><dc:creator>陈睿</dc:creator><author>陈睿</author><pubDate>Mon, 27 Feb 2012 07:35:00 GMT</pubDate><guid>http://www.blogjava.net/mikechen/archive/2012/02/27/370847.html</guid><wfw:comment>http://www.blogjava.net/mikechen/comments/370847.html</wfw:comment><comments>http://www.blogjava.net/mikechen/archive/2012/02/27/370847.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/mikechen/comments/commentRss/370847.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mikechen/services/trackbacks/370847.html</trackback:ping><description><![CDATA[<div><p><span style="font-size:18.0pt;color:red">JVM specification对JVM内存的描述</span> </p>  <p>首先我们来了解JVM specification中的JVM整体架构。如下图：</p>  <p>&nbsp;<img src="http://www.blogjava.net/images/blogjava_net/mikechen/虚拟机.jpg" border="0" alt="" width="409" height="394" /></p>  <span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;"><br /> &nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt; font-family:宋体;Times New Roman&quot;;">主要包括两个子系统和两个组件：</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;"> Class loader(</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">类装载器</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">) </span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">子系统，</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">Execution engine(</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">执行引擎</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">) </span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">子系统；</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">Runtime data area (</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">运行时数据区域</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">)</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">组件，</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;"> Native interface(</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">本地接口</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">)</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">组件。</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;"> <br /> &nbsp;&nbsp;&nbsp;&nbsp; <strong>Class loader</strong></span><strong><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">子系统的作用</span></strong> <span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">：根据给定的全限定名类名</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">(</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">如</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;"> java.lang.Object)</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">来装载</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">class</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">文件的内容到</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;"> Runtime data area</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">中的</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">method area(</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">方法区域</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">)</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">。</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">Javsa</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">程序员可以</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">extends java.lang.ClassLoader</span><span style="font-size:11.0pt; font-family:宋体;Times New Roman&quot;;">类来写自己的</span><span style="font-size: 11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">Class loader</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">。</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;"> <br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>Execution engine</strong></span><strong><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">子系统的作用</span></strong> <span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">：执行</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">classes</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">中的指令。任何</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">JVM specification</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">实现</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">(JDK)</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">的核心是</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">Execution engine</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">，</span> <span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">换句话说：</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">Sun </span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">的</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">JDK </span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">和</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">IBM</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">的</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">JDK</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">好坏主要取决于他们各自实现的</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">Execution&nbsp; engine</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">的好坏。每个运行中的线程都有一个</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">Execution engine</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">的实例。</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;"> <br /> &nbsp;&nbsp;&nbsp;&nbsp; <strong>Native interface</strong></span><strong><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">组件</span></strong> <span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">：与</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">native libraries</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;">交互，是其它编程语言交互的接口。</span><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp; <span style="color:red">Runtime data area </span></span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;; color:red;">组件：这个组件就是</span><span style="font-size:11.0pt;font-family: &quot;Calibri&quot;,&quot;sans-serif&quot;;Times New Roman&quot;; color:red;">JVM</span><span style="font-size:11.0pt;font-family:宋体;Times New Roman&quot;;color:red;">中的内存<br /><br /><ul><li><strong>运行时数据组件的详解介绍：</strong></li></ul>&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/images/blogjava_net/mikechen/虚拟机-内存管理.jpg" border="0" alt="" width="519" height="555" /><br /><br /><p><strong><span>Runtime data area 主要包括五个部分：Heap (堆), Method Area(方法区域), Java Stack(java的栈), Program Counter(程序计数器), Native method stack(本地方法栈)。Heap 和Method Area是被所有线程的共享使用的；而Java stack, Program counter 和Native method stack是以线程为粒度的，每个线程独自拥有。</span></strong><span> <br /> <br /> <strong>Heap</strong> <br /> Java程序在运行时创建的所有类实或数组都放在同一个堆中。</span>而一个<span>Java虚拟实例中只存在一个堆空间，因此所有线程都将共享这个堆。每一个java程序独占一个JVM实例，因而每个java程序都有它自己的堆空间，它们不会彼此干扰。但是同一java程序的多个线程都共享着同一个堆空间，就得考虑多线程访问对象（堆数据）的同步问题。 </span><span style="color:red">（这里可能出现的异常java.lang.OutOfMemoryError: Java heap space）</span><span> <br /></span></p><div><p style="margin:0cm;margin-bottom:.0001pt;text-indent:21.0pt"><span style="font-family: 楷体_GB2312; ">JVM堆一般又可以分为以下三部分：<br /><img src="http://www.blogjava.net/images/blogjava_net/mikechen/虚拟机-堆.jpg" border="0" alt="" width="462" height="243" /><br /></span></p>  <p><span style="font-family:Wingdings">&#216;&nbsp;</span><span style="font-family:楷体_GB2312">Perm</span></p>  <p style="margin:0cm;margin-bottom:.0001pt;text-indent:21.0pt"><span style="font-family:楷体_GB2312">Perm代主要保存</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">class,method,filed</span><span style="font-family:楷体_GB2312">对象，这部门的空间一般不会溢出，除非一次性加载了很多的类，不过在涉及到热部署的应用服务器的时候，有时候会遇到</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">java.lang.OutOfMemoryError&nbsp;:&nbsp;PermGen&nbsp;space&nbsp;</span><span style="font-family:楷体_GB2312">的错误，造成这个错误的很大原因就有可能是每次都重新部署，但是重新部署后，类的</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">class</span><span style="font-family:楷体_GB2312">没有被卸载掉，这样就造成了大量的</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">class</span><span style="font-family:楷体_GB2312">对象保存在了</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">perm</span><span style="font-family:楷体_GB2312">中，这种情况下，一般重新启动应用服务器可以解决问题。</span></p>  <p><span style="font-family:Wingdings">&#216;&nbsp;</span><span style="font-family:楷体_GB2312">Tenured</span></p>  <p style="margin-top:15.6pt;margin-right:0cm;margin-bottom:0cm; margin-left:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:inter-ideograph; text-indent:21.0pt"><span style="font-family:楷体_GB2312">Tenured区主要保存生命周期长的对象，一般是一些老的对象，当一些对象在</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">Young</span><span style="font-family:楷体_GB2312">复制转移一定的次数以后，对象就会被转移到</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">Tenured</span><span style="font-family:楷体_GB2312">区，一般如果系统中用了</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">application</span><span style="font-family:楷体_GB2312">级别的缓存，缓存中的对象往往会被转移到这一区间。</span></p>  <p><span style="font-family:Wingdings">&#216;&nbsp;</span><span style="font-family:楷体_GB2312">Young</span></p>  <p style="margin:0cm;margin-bottom:.0001pt;text-indent:21.0pt"><span style="font-family:楷体_GB2312;">Young</span><span style="font-family:楷体_GB2312;">区被划分为三部分，</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">Eden</span><span style="font-family:楷体_GB2312;">区和两个大小严格相同的</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">Survivor</span><span style="font-family:楷体_GB2312;">区，其中</span><span style="font-family: &quot;Times New Roman&quot;,&quot;serif&quot;;">Survivor</span><span style="font-family:楷体_GB2312;">区间中，某一时刻只有其中一个是被使用的，另外一个留做垃圾收集时复制对象用，在</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">Young</span><span style="font-family:楷体_GB2312;">区间变满的时候，</span><span style="font-family: &quot;Times New Roman&quot;,&quot;serif&quot;;">minor&nbsp;GC</span><span style="font-family:楷体_GB2312;">就会将存活的对象移到空闲的</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">Survivor</span><span style="font-family:楷体_GB2312;">区间中，根据</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">JVM</span><span style="font-family:楷体_GB2312;">的策略，在经过几次垃圾收集后，任然存活于</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">Survivor</span><span style="font-family:楷体_GB2312;">的对象将被移动到</span><span style="font-family: &quot;Times New Roman&quot;,&quot;serif&quot;;">Tenured</span><span style="font-family:楷体_GB2312;">区间。</span></p></div> <br /> <strong>Method area</strong> <br /> 在Java虚拟机中，被装载的class的信息存储在Method area的内存中。</span>当虚拟机装载某个类型时，它使用类装载器定位相应的<span>class文件，然后读入这个class文件内容并把它传输到虚拟机中。紧接着虚拟机提取其中的类型信息，并将这些信息存储到方法区。该类型中的类（静态）变量同样也存储在方法区中。与Heap 一样，method area是多线程共享的，因此要考虑多线程访问的同步问题。比如，假设同时两个线程都企图访问一个名为Lava的类，而这个类还没有内装载入虚拟机，那么，这时应该只有一个线程去装载它，而另一个线程则只能等待。 </span><span style="color:red">（这里可能出现的异常java.lang.OutOfMemoryError: PermGen full）<br /> </span><span><br /> <strong>Java stack</strong> <br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Java stack以帧为单位保存线程的运行状态。虚拟机只会直接对Java stack执行两种操作：以帧为单位的压栈或出栈。</span>每当线程调用一个方法的时候，就对当前状态作为一个帧保存到<span>java stack中(压栈)；当一个方法调用返回时，从java stack弹出一个帧(出栈)。<span style="color:red">栈的大小是有一定的限制，这个可能出现StackOverFlow问题。</span> </span>下面的程序可以说明这个问题。<p>&nbsp;</p>  <pre>public class TestStackOverFlow {</pre><pre>&nbsp;</pre><pre><span>&nbsp;&nbsp;&nbsp;&nbsp; public static void main(String[] args) {</span></pre><pre>&nbsp;</pre><pre><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Recursive r = new Recursive();</span></pre><pre><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r.doit(10000);</span></pre><pre><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Exception in thread "main" java.lang.StackOverflowError</span></pre><pre><span>&nbsp;&nbsp;&nbsp;&nbsp; }</span></pre><pre>&nbsp;</pre><pre>}</pre><pre>&nbsp;</pre><pre>class Recursive {</pre><pre>&nbsp;</pre><pre><span>&nbsp;&nbsp;&nbsp;&nbsp; public int doit(int t) {</span></pre><pre><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (t &lt;= 1) {</span></pre><pre><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 1;</span></pre><pre><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></pre><pre><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return t + doit(t - 1);</span></pre><pre><span>&nbsp;&nbsp;&nbsp;&nbsp; }</span></pre><pre>&nbsp;</pre><pre>}</pre>  <p><span>&nbsp;<br /> <br /> <strong>Program counter</strong> <br /> </span><span style="font-family:宋体;">每个运行中的</span>Java<span style="font-family:宋体;">程序，每一个线程都有它自己的</span>PC<span style="font-family:宋体;">寄存器，也是该线程启动时创建的。</span>PC<span style="font-family:宋体;">寄存器的内容总是指向下一条将被执行指令的饿</span>&amp;ldquo;<span style="font-family:宋体;">地址</span>&amp;rdquo;<span style="font-family:宋体;">，这里的</span>&amp;ldquo;<span style="font-family:宋体;">地址</span>&amp;rdquo;<span style="font-family:宋体;">可以是一个本地指针，也可以是在方法区中相对应于该方法起始指令的偏移量。</span><span> <br /> <br /> </span><strong><span>Native method stack</span></strong><span> <br /> </span><span style="font-family:宋体;">对于一个运行中的</span>Java<span style="font-family:宋体;">程序而言，它还能会用到一些跟本地方法相关的数据区。当某个线程调用一个本地方法时，它就进入了一个全新的并且不再受虚拟机限制的世界。本地方法可以通过本地方法接口来访问虚拟机的运行时数据区，不止与此，它还可以做任何它想做的事情。比如，可以调用寄存器，或在操作系统中分配内存等。总之，本地方法具有和</span>JVM<span style="font-family: 宋体;">相同的能力和权限。</span> <span style="color:red">(</span><span style="font-family:宋体;color:red">这里出现</span><span style="color:red">JVM</span><span style="font-family: 宋体;color:red">无法控制的内存溢出问题</span><span style="font-size:10.5pt;font-family:&quot;Times New Roman&quot;,&quot;serif&quot;; color:red">native heap OutOfMemory</span><span style="color:red"> )</span><span> <br /><br /><div><p style="margin:0cm;margin-bottom:.0001pt;text-indent:21.0pt"><span style="font-family: 楷体_GB2312; ">JVM提供了相应的参数来对内存大小进行配置。<br /></span></p>  <p align="center" style="margin-top: 0cm; margin-right: 0cm; margin-left: 0cm; margin-bottom: 0.0001pt; text-align: center; "><img src="http://www.blogjava.net/images/blogjava_net/mikechen/虚拟机-堆参数.jpg" border="0" alt="" width="448" height="255" /><br /><br /></p>  <p style="margin:0cm;margin-bottom:.0001pt;text-indent:21.0pt"><span style="font-family:楷体_GB2312;">正如上面描述，</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">JVM</span><span style="font-family:楷体_GB2312;">中堆被分为了</span><span style="font-family: &quot;Times New Roman&quot;,&quot;serif&quot;;">3</span><span style="font-family:楷体_GB2312;">个大的区间，同时</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">JVM</span><span style="font-family:楷体_GB2312;">也提供了一些选项对</span><span style="font-family: &quot;Times New Roman&quot;,&quot;serif&quot;;">Young,Tenured</span><span style="font-family:楷体_GB2312;">的大小进行控制。</span></p>  <p><span style="font-family:Wingdings;">&#216;&nbsp;</span><span style="font-family:楷体_GB2312;">Total</span>&nbsp;<span style="font-family:楷体_GB2312;">Heap</span>&nbsp;</p>  <p style="margin-top:15.6pt;margin-right:0cm;margin-bottom:0cm; margin-left:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:inter-ideograph"><span style="font-family:楷体_GB2312;">-Xms</span>&nbsp;<span style="font-family:楷体_GB2312;">：指定了</span><span style="font-family: &quot;Times New Roman&quot;,&quot;serif&quot;;">JVM</span><span style="font-family:楷体_GB2312;">初始启动以后初始化内存</span></p>  <p style="margin-top:15.6pt;margin-right:0cm;margin-bottom:0cm; margin-left:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:inter-ideograph"><span style="font-family:楷体_GB2312;">-Xmx</span><span style="font-family:楷体_GB2312;">：指定</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">JVM</span><span style="font-family:楷体_GB2312;">堆得最大内存，在</span><span style="font-family: &quot;Times New Roman&quot;,&quot;serif&quot;;">JVM</span><span style="font-family:楷体_GB2312;">启动以后，会分配</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">-Xmx</span><span style="font-family:楷体_GB2312;">参数指定大小的内存给</span><span style="font-family: &quot;Times New Roman&quot;,&quot;serif&quot;;">JVM</span><span style="font-family:楷体_GB2312;">，但是不一定全部使用，</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">JVM</span><span style="font-family:楷体_GB2312;">会根据</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">-Xms</span><span style="font-family:楷体_GB2312;">参数来调节真正用于</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">JVM</span><span style="font-family:楷体_GB2312;">的内存</span></p>  <p style="margin-top:15.6pt;margin-right:0cm;margin-bottom:0cm; margin-left:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:inter-ideograph"><span style="font-family:楷体_GB2312">-Xmx</span>&nbsp;<span style="font-family:楷体_GB2312">-Xms之差就是三个</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">Virtual</span><span style="font-family:楷体_GB2312">空间的大小</span></p>  <p><span style="font-family:Wingdings">&#216;&nbsp;</span><span style="font-family:楷体_GB2312">Young</span>&nbsp;<span style="font-family:楷体_GB2312">Generation</span></p>  <p style="margin-top:15.6pt;margin-right:0cm;margin-bottom:0cm; margin-left:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:inter-ideograph"><span style="font-family:楷体_GB2312">-XX:NewRatio=8意味着</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">tenured&nbsp;</span><span style="font-family:楷体_GB2312">和</span>&nbsp;<span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">young</span><span style="font-family:楷体_GB2312">的比值</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">8</span><span style="font-family:楷体_GB2312">：</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">1</span><span style="font-family:楷体_GB2312">，这样</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">eden+2*survivor=1/9</span></p>  <p style="margin-top:15.6pt;margin-right:0cm;margin-bottom:0cm; margin-left:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:inter-ideograph"><span style="font-family:楷体_GB2312">堆内存</span></p>  <p style="margin-top:15.6pt;margin-right:0cm;margin-bottom:0cm; margin-left:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:inter-ideograph"><span style="font-family:楷体_GB2312">-XX:SurvivorRatio=32意味着</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">eden</span><span style="font-family:楷体_GB2312">和一个</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">survivor</span><span style="font-family:楷体_GB2312">的比值是</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">32</span><span style="font-family:楷体_GB2312">：</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">1</span><span style="font-family:楷体_GB2312">，这样一个</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">Survivor</span><span style="font-family:楷体_GB2312">就占</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">Young</span><span style="font-family:楷体_GB2312">区的</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;;">1/34.</span></p>  <p style="margin-top:15.6pt;margin-right:0cm;margin-bottom:0cm; margin-left:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:inter-ideograph"><span style="font-family:楷体_GB2312;">-Xmn</span>&nbsp;<span style="font-family:楷体_GB2312;">参数设置了年轻代的大小</span></p>  <p><span style="font-family:Wingdings">&#216;&nbsp;</span><span style="font-family:楷体_GB2312">Perm</span>&nbsp;<span style="font-family:楷体_GB2312">Generation</span></p>  <p style="margin-top:15.6pt;margin-right:0cm;margin-bottom:0cm; margin-left:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:inter-ideograph"><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;">-XX:PermSize=</span><span style="font-family:楷体_GB2312">16</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;">M&nbsp;-XX:MaxPermSize=</span><span style="font-family:楷体_GB2312">64</span><span style="font-family:&quot;Times New Roman&quot;,&quot;serif&quot;">M</span></p>  <p style="margin-top:15.6pt;margin-right:0cm;margin-bottom:0cm; margin-left:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:inter-ideograph"><strong><span style="font-size:10.5pt;font-family:楷体_GB2312;color:black; background:white;">Thread</span></strong><strong>&nbsp;</strong><span style="font-family:楷体_GB2312;">Stack</span></p>  <p style="text-align:justify;text-justify:inter-ideograph;background: white"><strong><span style="font-size:10.5pt;font-family:楷体_GB2312; color:black;background:white;">-XX:Xss=128K</span></strong></p>  <p style="background:white">&nbsp;</p></div> <br /></span></p></div><img src ="http://www.blogjava.net/mikechen/aggbug/370847.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mikechen/" target="_blank">陈睿</a> 2012-02-27 15:35 <a href="http://www.blogjava.net/mikechen/archive/2012/02/27/370847.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线程</title><link>http://www.blogjava.net/mikechen/archive/2012/02/21/370416.html</link><dc:creator>陈睿</dc:creator><author>陈睿</author><pubDate>Tue, 21 Feb 2012 07:32:00 GMT</pubDate><guid>http://www.blogjava.net/mikechen/archive/2012/02/21/370416.html</guid><wfw:comment>http://www.blogjava.net/mikechen/comments/370416.html</wfw:comment><comments>http://www.blogjava.net/mikechen/archive/2012/02/21/370416.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mikechen/comments/commentRss/370416.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mikechen/services/trackbacks/370416.html</trackback:ping><description><![CDATA[<strong>1.&nbsp;&nbsp;&nbsp;&nbsp;多线程概念：<br /></strong>&nbsp;&nbsp; &nbsp; &nbsp; 线程是指进程中的一个执行流程，一个进程中可以运行多个线程。比如java.exe进程中可以运行很多线程。线程总是属于某个进程，进程中的多个线程共享进程的内存。<ul><li>&nbsp;&nbsp; &nbsp;多线程的实现方式和启动</li><li>&nbsp;&nbsp; &nbsp;多线程是依靠什么方式解决资源竞争</li><li>&nbsp;&nbsp; &nbsp;多线程的各种状态以及优先级</li><li>&nbsp;&nbsp; &nbsp;多线程的暂停方式</li></ul><strong>&nbsp;2.&nbsp;&nbsp;&nbsp;&nbsp;多线程详解</strong><br />&nbsp;&nbsp; &nbsp; &nbsp; <strong>&nbsp;1）多线程的实现方式和启动:</strong><br /><ul><li>&nbsp;&nbsp; &nbsp; &nbsp;继承Thread和是实现Runnable接口，重写run方法</li><li>&nbsp;&nbsp; &nbsp; &nbsp;启动只有一种方式：通过start方法，虚拟机会调用run方法</li></ul><br />&nbsp;&nbsp; &nbsp; <strong>&nbsp; 2） 多线程依靠什么解决资源竞争</strong><br /><ul><li>&nbsp;&nbsp; &nbsp; &nbsp; 锁机制：分为对象锁和类锁，在多个线程调用的情况，每个对象锁都是唯一的，只有获取了锁才能调用synchronized方法</li><li>&nbsp;&nbsp; &nbsp; &nbsp; synchronize同步：分为同步方法和同步方法块</li><li>&nbsp;&nbsp; &nbsp; &nbsp; 什么时候获取锁：每次调用到synchronize方法，这个时候去获取锁资源，如果线程获取到锁则别的线程只有等到同步方法介绍后，释放锁后，别的线程 &nbsp; &nbsp; &nbsp; &nbsp;才能继续使用</li></ul>&nbsp;&nbsp; &nbsp; &nbsp; <strong>&nbsp;3）线程的几种状态</strong><br /><ul><li>&nbsp;&nbsp; &nbsp; &nbsp; 主要分为：新状态（还没有调用start方法），可执行状态（调用start方法），阻塞状态，死亡状态</li></ul>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;默认优先级为normal(5),优先级数值在1-10之间<br /><strong>&nbsp;4)&nbsp;多线程的暂停方式</strong><br /><br /><ul><li>&nbsp;&nbsp; &nbsp;sleep:睡眠单位为毫秒</li><li>&nbsp;&nbsp; &nbsp;wait,waitAll,notify,notifyAll,wait等待，只有通过wait或者waitAll唤醒</li><li>&nbsp;&nbsp; &nbsp;yield：cpu暂时停用</li><li>&nbsp;&nbsp; &nbsp;join</li></ul><img src ="http://www.blogjava.net/mikechen/aggbug/370416.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mikechen/" target="_blank">陈睿</a> 2012-02-21 15:32 <a href="http://www.blogjava.net/mikechen/archive/2012/02/21/370416.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>容器-Set-HashSet</title><link>http://www.blogjava.net/mikechen/archive/2012/02/21/370398.html</link><dc:creator>陈睿</dc:creator><author>陈睿</author><pubDate>Tue, 21 Feb 2012 03:37:00 GMT</pubDate><guid>http://www.blogjava.net/mikechen/archive/2012/02/21/370398.html</guid><wfw:comment>http://www.blogjava.net/mikechen/comments/370398.html</wfw:comment><comments>http://www.blogjava.net/mikechen/archive/2012/02/21/370398.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mikechen/comments/commentRss/370398.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mikechen/services/trackbacks/370398.html</trackback:ping><description><![CDATA[<ol><li><strong>HashSet概要</strong>：</li></ol><ul><li>&nbsp;&nbsp; &nbsp;采用HashMap存储，key直接存取值，value存储一个object</li><li>&nbsp;&nbsp; &nbsp;存储的key值是唯一的</li><li><span class="Apple-style-span" style="font-family: Arial; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; line-height: normal; ">&nbsp;&nbsp; &nbsp; HashSet中元素的顺序是随机的，包括添加(add())和输出都是无序的<br /><br /><strong>代码就不具体详解了，主要就是通过封装HashMap组成。</strong><br /><br /></span></li></ul><div></div><img src ="http://www.blogjava.net/mikechen/aggbug/370398.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mikechen/" target="_blank">陈睿</a> 2012-02-21 11:37 <a href="http://www.blogjava.net/mikechen/archive/2012/02/21/370398.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>容器-Map-Hashtable</title><link>http://www.blogjava.net/mikechen/archive/2012/02/21/370390.html</link><dc:creator>陈睿</dc:creator><author>陈睿</author><pubDate>Tue, 21 Feb 2012 02:32:00 GMT</pubDate><guid>http://www.blogjava.net/mikechen/archive/2012/02/21/370390.html</guid><wfw:comment>http://www.blogjava.net/mikechen/comments/370390.html</wfw:comment><comments>http://www.blogjava.net/mikechen/archive/2012/02/21/370390.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mikechen/comments/commentRss/370390.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mikechen/services/trackbacks/370390.html</trackback:ping><description><![CDATA[<strong>1.Hashtable概要：实现Map接口的同步实现</strong><br /><ul><li>&nbsp;&nbsp; &nbsp;线程安全</li><li>&nbsp;&nbsp; &nbsp;不能存储null到key和value</li><li><span class="Apple-style-span" style="font-family: 宋体; line-height: 24px; ">&nbsp;&nbsp; HashTable中hash数组默认大小是11，增加的方式是 old*2+1。HashMap中hash数组的默认大小是16，而且一定是2的指数<br /><br /><div><table bordercolor="#000000" cellspacing="1" cellpadding="0" width="588" align="center" bgcolor="#000000" border="0" style="font-size: 12px; margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; "><tbody><tr style="font-size: 12px; "><td valign="top" width="110" bgcolor="#ffffff" style="font-size: 12px; "><p align="center">区别</p></td><td valign="top" width="225" bgcolor="#ffffff" style="font-size: 12px; "><p align="center">Hashtable</p></td><td valign="top" width="322" bgcolor="#ffffff" style="font-size: 12px; "><p align="center">Hashmap</p></td></tr><tr style="font-size: 12px; "><td valign="top" width="110" bgcolor="#ffffff" style="font-size: 12px; "><p align="left">继承、实现</p></td><td valign="top" width="225" bgcolor="#ffffff" style="font-size: 12px; "><p align="left">Hashtable<k,v>&nbsp;extends Dictionary<k,v>implements Map<k,v>, Cloneable,Serializable</k,v></k,v></k,v></p></td><td valign="top" width="322" bgcolor="#ffffff" style="font-size: 12px; "><p align="left">HashMap<k,v>&nbsp;extends AbstractMap<k,v>&nbsp;<wbr>implements Map<k,v>, Cloneable,Serializable</k,v></k,v></k,v></p></td></tr><tr style="font-size: 12px; "><td valign="top" width="110" bgcolor="#ffffff" style="font-size: 12px; "><p align="left">线程同步</p></td><td valign="top" width="225" bgcolor="#ffffff" style="font-size: 12px; "><p align="left">已经同步过的可以安全使用</p></td><td valign="top" width="322" bgcolor="#ffffff" style="font-size: 12px; "><p align="left">未同步的，可以使用Colletcions进行同步Map&nbsp;<wbr>Collections.synchronizedMap(Map&nbsp;<wbr>m)</p></td></tr><tr style="font-size: 12px; "><td valign="top" width="110" bgcolor="#ffffff" style="font-size: 12px; "><p align="left">对null的处理</p><p align="left"><wbr></p></td><td valign="top" width="225" bgcolor="#ffffff" style="font-size: 12px; "><p align="left">Hashtable table = new Hashtable();</p><p align="left">table.put(null, "Null");</p><p align="left">table.put("Null", null);</p><p align="left">table.contains(null);</p><p align="left">table.containsKey(null);</p><p align="left">table.containsValue(null);</p><p align="left">后面的5句话在编译的时候不会有异常，可在运行的时候会报空指针异常具体原因可以查看源代码</p><p align="left">public synchronized V put(K key, V value) {</p><p align="left"><wbr><wbr><wbr><wbr>// Make sure the value is not null</p><p align="left"><wbr>if (value == null) {</p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr>throw new NullPointerException();</p><p align="left">}</p></td><td valign="top" width="322" bgcolor="#ffffff" style="font-size: 12px; "><p align="left">HashMap map = new HashMap();<br />map.put(null, "Null");</p><p align="left">map.put("Null", null);</p><p align="left">map.containsKey(null);</p><p align="left">map.containsValue(null);</p><p align="left">以上这5条语句无论在编译期，还是在运行期都是没有错误的.</p><p align="left">在HashMap中，null可以作为键，这样的键只有一个；可以有一个或多个键所对应的值为null。当get()方法返回null值时，即可以表示 HashMap中没有该键，也可以表示该键所对应的值为null。因此，在HashMap中不能由get()方法来判断HashMap中是否存在某个键，而应该用containsKey()方法来判断。</p></td></tr><tr style="font-size: 12px; "><td valign="top" width="110" bgcolor="#ffffff" style="font-size: 12px; "><p align="left">增长率</p></td><td valign="top" width="225" bgcolor="#ffffff" style="font-size: 12px; "><p><wbr><wbr><wbr>protected void rehash() {</p><p align="left"><wbr><wbr><wbr><wbr><wbr>int oldCapacity = table.length;</p><p align="left"><wbr><wbr><wbr><wbr><wbr>Entry[] oldMap = table;</p><p align="left"><wbr><wbr><wbr><wbr><wbr>int newCapacity = oldCapacity * 2 + 1;</p><p align="left"><wbr><wbr><wbr><wbr><wbr>Entry[] newMap = new Entry[newCapacity];</p><p align="left"><wbr><wbr><wbr><wbr><wbr>modCount++;</p><p align="left"><wbr><wbr><wbr><wbr><wbr>threshold = (int)(newCapacity * loadFactor);</p><p align="left"><wbr><wbr><wbr><wbr><wbr>table = newMap;</p><p align="left"><wbr><wbr><wbr><wbr><wbr>for (int i = oldCapacity ; i-- &gt; 0 ;) {</p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>for (Entry<k,v>&nbsp;old = oldMap[i] ; old != null ; ) {</k,v></p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>Entry<k,v>&nbsp;e = old;</k,v></p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>old = old.next;</p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>int index = (e.hash &amp; 0x7FFFFFFF) % newCapacity;</p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>e.next = newMap[index];</p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>newMap[index] = e;</p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>}</p><p align="left"><wbr><wbr><wbr><wbr><wbr>}</p><p align="left"><wbr><wbr><wbr>}</p><p align="left"><wbr></p></td><td valign="top" width="322" bgcolor="#ffffff" style="font-size: 12px; "><p align="left">void addEntry(int hash, K key, V value, int bucketIndex) {</p><p align="left"><wbr><wbr><wbr><wbr><wbr>Entry<k,v>&nbsp;e = table[bucketIndex];</k,v></p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr>table[bucketIndex] = new Entry<k,v>(hash, key, value, e);</k,v></p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr>if (size++ &gt;= threshold)</p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>resize(2 * table.length);</p><p align="left"><wbr><wbr><wbr>}</p><p align="left"><wbr></p></td></tr><tr style="font-size: 12px; "><td valign="top" width="110" bgcolor="#ffffff" style="font-size: 12px; "><p align="left">哈希值的使用</p></td><td valign="top" width="225" bgcolor="#ffffff" style="font-size: 12px; "><p align="left">HashTable直接使用对象的hashCode，代码是这样的：</p><p align="left"><strong>public</strong>&nbsp;<strong>synchronized</strong>&nbsp;<strong>boolean</strong>containsKey(Object key) {</p><p align="left"><wbr><wbr><wbr><wbr><wbr>Entry tab[] = table;</p><p align="left"><wbr><wbr><wbr><wbr><wbr><strong>int</strong>&nbsp;hash = key.hashCode();</p><p align="left"><wbr><wbr><wbr><wbr><wbr><strong>int</strong>&nbsp;index = (hash &amp; 0x7FFFFFFF) % tab.length;</p><p align="left"><wbr><wbr><wbr><wbr><wbr><strong>for</strong>&nbsp;(Entry<k,v>&nbsp;e = tab[index] ; e !=<strong>null</strong>&nbsp;; e = e.next) {</k,v></p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><strong>if</strong>&nbsp;((e.hash == hash) &amp;&amp; e.key.equals(key)) {</p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><strong>return</strong>&nbsp;<strong>true</strong>;</p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>}</p><p align="left"><wbr><wbr><wbr><wbr><wbr>}</p><p align="left"><wbr><wbr><wbr><wbr><wbr><strong>return</strong>&nbsp;<strong>false</strong>;</p><p align="left"><wbr><wbr><wbr>}</p></td><td valign="top" width="322" bgcolor="#ffffff" style="font-size: 12px; "><p align="left">HashMap重新计算hash值，而且用与代替求模</p><p align="left"><wbr><wbr><wbr><wbr><wbr>public boolean containsKey(Object key) {</p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>Object k = maskNull(key);</p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>int hash = hash(k.hashCode());</p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>int i = indexFor(hash, table.length);</p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>Entry e = table[i];</p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>while (e != null) {</p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>if (e.hash == hash &amp;&amp; eq(k, e.key))</p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>return true;</p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>e = e.next;</p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>}</p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>return false;</p><p align="left"><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>}</p></td></tr></tbody></table></div></span></li></ul><div></div><img src ="http://www.blogjava.net/mikechen/aggbug/370390.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mikechen/" target="_blank">陈睿</a> 2012-02-21 10:32 <a href="http://www.blogjava.net/mikechen/archive/2012/02/21/370390.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>容器-Map-HashMap</title><link>http://www.blogjava.net/mikechen/archive/2012/02/20/370353.html</link><dc:creator>陈睿</dc:creator><author>陈睿</author><pubDate>Mon, 20 Feb 2012 08:40:00 GMT</pubDate><guid>http://www.blogjava.net/mikechen/archive/2012/02/20/370353.html</guid><wfw:comment>http://www.blogjava.net/mikechen/comments/370353.html</wfw:comment><comments>http://www.blogjava.net/mikechen/archive/2012/02/20/370353.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mikechen/comments/commentRss/370353.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mikechen/services/trackbacks/370353.html</trackback:ping><description><![CDATA[<strong>1. &nbsp;HashMap概要：基于哈希表Map接口的非同步实现</strong><br /> <ul><li>线程不安全,线程安全请使用Hashtable</li><li>效率较好</li><li>提供null作为key或者value</li></ul><br /><strong>2. &nbsp;HashMap代码详解</strong>：<br /><ul><li>&nbsp;&nbsp; &nbsp;默认 初始化<br /></li></ul>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="Apple-style-span" style="font-size: 13px; "><span style="color: #000000; ">&nbsp;</span><span style="color: #008000; ">/**</span></span><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Constructs&nbsp;an&nbsp;empty&nbsp;&lt;tt&gt;HashMap&lt;/tt&gt;&nbsp;with&nbsp;the&nbsp;default&nbsp;initial&nbsp;capacity<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;(16)&nbsp;and&nbsp;the&nbsp;default&nbsp;load&nbsp;factor&nbsp;(0.75).<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;HashMap()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">.loadFactor&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;DEFAULT_LOAD_FACTOR; &nbsp; &nbsp; &nbsp; &nbsp;</span><span style="color: #ff6600; "><strong>//默认是0.75</strong></span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threshold&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">)(DEFAULT_INITIAL_CAPACITY&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;DEFAULT_LOAD_FACTOR);</span><span style="color: #ff6600; "><strong>//扩容的门槛，存入的数据大于该值，容量扩充一倍</strong></span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;Entry[DEFAULT_INITIAL_CAPACITY];</span><span style="color: #ff6600; "><strong>//初始化数组，数组内容为Entry，存储链表</strong>&nbsp;&nbsp; &nbsp;</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init();<br /></span></div><br /><ul><li><strong>存入元素：</strong></li></ul><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;V&nbsp;put(K&nbsp;key,&nbsp;V&nbsp;value)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(key&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;putForNullKey(value);</span><span style="color: #ff6600; "><strong>//如果key为null，直接把value放到数组第一位table[0]</strong></span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;hash&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;hash(key.hashCode());</span><span style="color: #ff6600; "><strong>//通过可以的hashcode计算对应的hash值</strong></span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;i&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;indexFor(hash,&nbsp;table.length);</span><span style="color: #ff6600; "><strong>//通过hash值，把entry对应到数组的位数计算出来</strong></span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;(Entry</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">K,V</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;e&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;table[i];&nbsp;e&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">;&nbsp;e&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;e.next)&nbsp;{</span><span style="color: #ff6600; "><strong>//如果该entry还包含下一个entry的引用，则继续遍历该链表</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;k;<br /></span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(e.hash&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;hash&nbsp;</span><span style="color: #000000; ">&amp;&amp;</span><span style="color: #000000; ">&nbsp;((k&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;e.key)&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;key&nbsp;</span><span style="color: #000000; ">||</span><span style="color: #000000; ">&nbsp;key.equals(k)))&nbsp;{</span><span style="color: #ff6600; "><strong>//如果key相同，则替换新的value到制定的key</strong></span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;V&nbsp;oldValue&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;e.value;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.value&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;value;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.recordAccess(</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;oldValue;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;modCount</span><span style="color: #000000; ">++</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;addEntry(hash,&nbsp;key,&nbsp;value,&nbsp;i);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}</span></div><br /><ul><li><strong>读取元素：</strong></li></ul><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;V&nbsp;get(Object&nbsp;key)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(key&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">)</span><span style="color: #ff6600; "><strong>//key为null，直接从数组第一位拿数据</strong></span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;getForNullKey();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;hash&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;hash(key.hashCode());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;(Entry</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">K,V</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;e&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;table[indexFor(hash,&nbsp;table.length)]; &nbsp;</span><span style="color: #ff6600; "><strong>//直接通过key的hashcode计算出对应到数组的索引位，直接取数据，如果有链表继续查找</strong></span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;e.next)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;k;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(e.hash&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;hash&nbsp;</span><span style="color: #000000; ">&amp;&amp;</span><span style="color: #000000; ">&nbsp;((k&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;e.key)&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;key&nbsp;</span><span style="color: #000000; ">||</span><span style="color: #000000; ">&nbsp;key.equals(k)))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;e.value;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span></div><br /><br /><br /><ul><li><strong>总结：</strong></li></ul>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;HashMap别的方法就不继续详解了，主要通过put与get可以很好的理解HashMap底层的结构，以及工作方式。<br /><br /><br /><br /><br /><br /><br /><br /><br /><img src ="http://www.blogjava.net/mikechen/aggbug/370353.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mikechen/" target="_blank">陈睿</a> 2012-02-20 16:40 <a href="http://www.blogjava.net/mikechen/archive/2012/02/20/370353.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>容器-数组-Vector</title><link>http://www.blogjava.net/mikechen/archive/2012/02/20/370351.html</link><dc:creator>陈睿</dc:creator><author>陈睿</author><pubDate>Mon, 20 Feb 2012 08:11:00 GMT</pubDate><guid>http://www.blogjava.net/mikechen/archive/2012/02/20/370351.html</guid><wfw:comment>http://www.blogjava.net/mikechen/comments/370351.html</wfw:comment><comments>http://www.blogjava.net/mikechen/archive/2012/02/20/370351.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mikechen/comments/commentRss/370351.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mikechen/services/trackbacks/370351.html</trackback:ping><description><![CDATA[<div><strong style="font-size: 12pt; ">1. Vector概要：</strong><br /><ul><li><strong>默认长度为10</strong></li></ul>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="Apple-style-span" style="font-size: 13px; "><span style="color: #000000; ">&nbsp;</span><span style="color: #008000; ">/**</span></span><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Constructs&nbsp;an&nbsp;empty&nbsp;vector&nbsp;so&nbsp;that&nbsp;its&nbsp;internal&nbsp;data&nbsp;array<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;has&nbsp;size&nbsp;{</span><span style="color: #808080; ">@code</span><span style="color: #008000; ">&nbsp;10}&nbsp;and&nbsp;its&nbsp;standard&nbsp;capacity&nbsp;increment&nbsp;is<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;zero.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;Vector()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">(</span><span style="color: #000000; ">10</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}</span></div><ul><li><strong>底层采用数组存储</strong>：<span class="Apple-style-span" style="font-size: 13px; "><span style="color: #0000FF; ">protected</span><span style="color: #000000; ">&nbsp;Object[]&nbsp;elementData;</span></span></li></ul><ul><li><strong>线程安全</strong></li><li><strong>查询效率比较高，比较适用于查询</strong></li><li><strong>扩容的长度为初始长度的一半，建议初始化的时候设置已知的长度，免得容器自己去扩容，浪费空间以及效率<br />与ArrayList基本一样，除了所有操作资源的方法都加了</strong>synchronized，保证线程同步<br />这里的源代码就不详解了，具体请参考<a href="http://www.blogjava.net/mikechen/articles/370346.html" title="容器-数组-ArrayList详解">容器-数组-ArrayList详解</a>。</li></ul></div><img src ="http://www.blogjava.net/mikechen/aggbug/370351.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mikechen/" target="_blank">陈睿</a> 2012-02-20 16:11 <a href="http://www.blogjava.net/mikechen/archive/2012/02/20/370351.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>容器-数组-ArrayList</title><link>http://www.blogjava.net/mikechen/archive/2012/02/20/370346.html</link><dc:creator>陈睿</dc:creator><author>陈睿</author><pubDate>Mon, 20 Feb 2012 06:28:00 GMT</pubDate><guid>http://www.blogjava.net/mikechen/archive/2012/02/20/370346.html</guid><wfw:comment>http://www.blogjava.net/mikechen/comments/370346.html</wfw:comment><comments>http://www.blogjava.net/mikechen/archive/2012/02/20/370346.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mikechen/comments/commentRss/370346.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mikechen/services/trackbacks/370346.html</trackback:ping><description><![CDATA[<strong style="font-size: 12pt; ">1. ArrayList概要：</strong><br /><ul><li><strong>默认长度为10</strong></li></ul>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="Apple-style-span" style="font-size: 13px; "><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;ArrayList()&nbsp;{</span></span><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">this</span><span style="color: #000000; ">(</span><span style="color: #000000; ">10</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></div><ul><li><strong>底层采用数组存储</strong>：<span class="Apple-style-span" style="font-size: 13px; "><span style="color: #0000FF; ">private</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">transient</span><span style="color: #000000; ">&nbsp;Object[]&nbsp;elementData;</span></span></li></ul>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;transient表示数组elementData不需要通过serialization序列化传输<br /><ul><li><strong>线程不安全，在多线程场景会出现问题，可以考虑使用Vector或者Collections.synchronizedList同步该容器</strong></li><li><strong>查询效率比较高，比较适用于查询</strong></li><li><strong>扩容的长度为初始长度的一半，建议初始化的时候设置已知的长度，免得容器自己去扩容，浪费空间以及效率</strong></li></ul><br /><strong style="font-size: 12pt; ">2. ArrayList代码详解：</strong><br /><br /><ul><li><strong>增加元素</strong></li></ul><span class="Apple-style-span" style="font-size: 13px; "><span style="color: #0000FF; ">&nbsp;&nbsp;public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">boolean</span><span style="color: #000000; ">&nbsp;add(E&nbsp;e)&nbsp;{</span></span><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;ensureCapacity(size&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">);&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Increments&nbsp;modCount!!</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;elementData[size</span><span style="color: #000000; ">++</span><span style="color: #000000; ">]&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;e;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>首先检查数组是否已满，如果满了就开始扩容，扩容后的长度为原长度的1.5倍。<span class="Apple-style-span" style="font-size: 13px; "><span style="color: #000000; "><br /></span><span style="color: #008000; ">/**</span></span><div style="background-color: #eeeeee; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><span style="color: #008000; font-size: 13px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Increases&nbsp;the&nbsp;capacity&nbsp;of&nbsp;this&nbsp;&lt;tt&gt;ArrayList&lt;/tt&gt;&nbsp;instance,&nbsp;if<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;necessary,&nbsp;to&nbsp;ensure&nbsp;that&nbsp;it&nbsp;can&nbsp;hold&nbsp;at&nbsp;least&nbsp;the&nbsp;number&nbsp;of&nbsp;elements<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;specified&nbsp;by&nbsp;the&nbsp;minimum&nbsp;capacity&nbsp;argument.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; font-size: 13px; ">@param</span><span style="color: #008000; font-size: 13px; ">&nbsp;&nbsp;&nbsp;minCapacity&nbsp;&nbsp;&nbsp;the&nbsp;desired&nbsp;minimum&nbsp;capacity<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; font-size: 13px; ">*/</span><span style="color: #000000; font-size: 13px; "><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 13px; ">public</span><span style="color: #000000; font-size: 13px; ">&nbsp;</span><span style="color: #0000ff; font-size: 13px; ">void</span><span style="color: #000000; font-size: 13px; ">&nbsp;ensureCapacity(</span><span style="color: #0000ff; font-size: 13px; ">int</span><span style="color: #000000; font-size: 13px; ">&nbsp;minCapacity)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;modCount</span><span style="color: #000000; font-size: 13px; ">++</span><font class="Apple-style-span" size="2">;<span style="color: red; ">//modCount表示数组的操作计数，用于iterator的时候与</span></font><div style="display: inline-block; color: #000000; font-size: 13px; "><div><span class="Apple-style-span" style="font-family: 宋体; font-size: 14px; line-height: 24px; color: red; ">expectedMod<br /></span></div></div><font class="Apple-style-span" size="2"><span style="color: red; ">Count比较，防止迭代操作对add,remove等操作影响迭代操作</span><br />&nbsp;&nbsp;</font><span style="color: #0000ff; font-size: 13px; ">int</span><span style="color: #000000; font-size: 13px; ">&nbsp;oldCapacity&nbsp;</span><span style="color: #000000; font-size: 13px; ">=</span><span style="color: #000000; font-size: 13px; ">&nbsp;elementData.length;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 13px; ">if</span><span style="color: #000000; font-size: 13px; ">&nbsp;(minCapacity&nbsp;</span><span style="color: #000000; font-size: 13px; ">&gt;</span><span style="color: #000000; font-size: 13px; ">&nbsp;oldCapacity)&nbsp;{ &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: red; font-size: 13px; ">//新插入元素后的长度大于老的长度，数组开始扩容</span><span style="color: #000000; font-size: 13px; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;oldData[]&nbsp;</span><span style="color: #000000; font-size: 13px; ">=</span><span style="color: #000000; font-size: 13px; ">&nbsp;elementData;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 13px; ">int</span><span style="color: #000000; font-size: 13px; ">&nbsp;newCapacity&nbsp;</span><span style="color: #000000; font-size: 13px; ">=</span><span style="color: #000000; font-size: 13px; ">&nbsp;(oldCapacity&nbsp;</span><span style="color: #000000; font-size: 13px; ">*</span><span style="color: #000000; font-size: 13px; ">&nbsp;</span><span style="color: #000000; font-size: 13px; ">3</span><span style="color: #000000; font-size: 13px; ">)</span><span style="color: #000000; font-size: 13px; ">/</span><span style="color: #000000; font-size: 13px; ">2</span><span style="color: #000000; font-size: 13px; ">&nbsp;</span><span style="color: #000000; font-size: 13px; ">+</span><span style="color: #000000; font-size: 13px; ">&nbsp;</span><span style="color: #000000; font-size: 13px; ">1</span><span style="color: #000000; font-size: 13px; ">;</span><span style="color: red; font-size: 13px; ">//新空间为原长度的1.5倍，等于是扩容了50%</span><span style="color: #000000; font-size: 13px; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 13px; ">if</span><span style="color: #000000; font-size: 13px; ">&nbsp;(newCapacity&nbsp;</span><span style="color: #000000; font-size: 13px; ">&lt;</span><span style="color: #000000; font-size: 13px; ">&nbsp;minCapacity)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newCapacity&nbsp;</span><span style="color: #000000; font-size: 13px; ">=</span><span style="color: #000000; font-size: 13px; ">&nbsp;minCapacity;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; font-size: 13px; ">//</span><span style="color: #008000; font-size: 13px; ">&nbsp;minCapacity&nbsp;is&nbsp;usually&nbsp;close&nbsp;to&nbsp;size,&nbsp;so&nbsp;this&nbsp;is&nbsp;a&nbsp;win:</span><span style="color: #008000; font-size: 13px; "><br /></span><span style="color: #000000; font-size: 13px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elementData&nbsp;</span><span style="color: #000000; font-size: 13px; ">=</span><span style="color: #000000; font-size: 13px; ">&nbsp;Arrays.copyOf(elementData,&nbsp;newCapacity);</span><span style="color: red; font-size: 13px; ">//把之前的元素拷贝到新的数组&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #000000; font-size: 13px; "><br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span></div><br /><ul><li><strong>删除元素：</strong></li></ul><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">/**</span><span style="color: #008000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Removes&nbsp;the&nbsp;element&nbsp;at&nbsp;the&nbsp;specified&nbsp;position&nbsp;in&nbsp;this&nbsp;list.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Shifts&nbsp;any&nbsp;subsequent&nbsp;elements&nbsp;to&nbsp;the&nbsp;left&nbsp;(subtracts&nbsp;one&nbsp;from&nbsp;their<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;indices).<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;index&nbsp;the&nbsp;index&nbsp;of&nbsp;the&nbsp;element&nbsp;to&nbsp;be&nbsp;removed<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@return</span><span style="color: #008000; ">&nbsp;the&nbsp;element&nbsp;that&nbsp;was&nbsp;removed&nbsp;from&nbsp;the&nbsp;list<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@throws</span><span style="color: #008000; ">&nbsp;IndexOutOfBoundsException&nbsp;{</span><span style="color: #808080; ">@inheritDoc</span><span style="color: #008000; ">}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;E&nbsp;remove(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;index)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;RangeCheck(index); //检查索引是否溢出<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;modCount</span><span style="color: #000000; ">++</span><span style="color: #000000; ">; &nbsp; &nbsp; &nbsp; &nbsp;//操作计数<br />&nbsp;&nbsp;&nbsp;&nbsp;E&nbsp;oldValue&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(E)&nbsp;elementData[index];<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;numMoved&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;size&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;index&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(numMoved&nbsp;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.arraycopy(elementData,&nbsp;index</span><span style="color: #000000; ">+</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;elementData,&nbsp;index,//复制原数组制定index+1到length-1的元素到elementData的index的索引位<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;numMoved);<br />&nbsp;&nbsp;&nbsp;&nbsp;elementData[</span><span style="color: #000000; ">--</span><span style="color: #000000; ">size]&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Let&nbsp;gc&nbsp;do&nbsp;its&nbsp;work//最后一位设置为null</span><span style="color: #008000; "><br /></span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;oldValue;<br />&nbsp;&nbsp;&nbsp;&nbsp;}</span></div><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">&nbsp;</span><span style="color: #008000; ">/**</span><span style="color: #008000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Checks&nbsp;if&nbsp;the&nbsp;given&nbsp;index&nbsp;is&nbsp;in&nbsp;range.&nbsp;&nbsp;If&nbsp;not,&nbsp;throws&nbsp;an&nbsp;appropriate<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;runtime&nbsp;exception.&nbsp;&nbsp;This&nbsp;method&nbsp;does&nbsp;*not*&nbsp;check&nbsp;if&nbsp;the&nbsp;index&nbsp;is<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;negative:&nbsp;It&nbsp;is&nbsp;always&nbsp;used&nbsp;immediately&nbsp;prior&nbsp;to&nbsp;an&nbsp;array&nbsp;access,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;which&nbsp;throws&nbsp;an&nbsp;ArrayIndexOutOfBoundsException&nbsp;if&nbsp;index&nbsp;is&nbsp;negative.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;RangeCheck(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;index)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(index&nbsp;</span><span style="color: #000000; ">&gt;=</span><span style="color: #000000; ">&nbsp;size)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">throw</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;IndexOutOfBoundsException(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Index:&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">+</span><span style="color: #000000; ">index</span><span style="color: #000000; ">+</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;Size:&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">+</span><span style="color: #000000; ">size);<br />&nbsp;&nbsp;&nbsp;&nbsp;}</span></div><br /><ul><li><strong>获取元素：</strong></li></ul><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">&nbsp;</span><span style="color: #008000; ">/**</span><span style="color: #008000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Returns&nbsp;the&nbsp;element&nbsp;at&nbsp;the&nbsp;specified&nbsp;position&nbsp;in&nbsp;this&nbsp;list.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;&nbsp;index&nbsp;index&nbsp;of&nbsp;the&nbsp;element&nbsp;to&nbsp;return<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@return</span><span style="color: #008000; ">&nbsp;the&nbsp;element&nbsp;at&nbsp;the&nbsp;specified&nbsp;position&nbsp;in&nbsp;this&nbsp;list<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@throws</span><span style="color: #008000; ">&nbsp;IndexOutOfBoundsException&nbsp;{</span><span style="color: #808080; ">@inheritDoc</span><span style="color: #008000; ">}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;E&nbsp;get(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;index)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;RangeCheck(index);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;(E)&nbsp;elementData[index]; &nbsp; //直接获取数组的索引位<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span></div><img src ="http://www.blogjava.net/mikechen/aggbug/370346.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mikechen/" target="_blank">陈睿</a> 2012-02-20 14:28 <a href="http://www.blogjava.net/mikechen/archive/2012/02/20/370346.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java高级知识概要</title><link>http://www.blogjava.net/mikechen/archive/2012/02/20/370343.html</link><dc:creator>陈睿</dc:creator><author>陈睿</author><pubDate>Mon, 20 Feb 2012 06:09:00 GMT</pubDate><guid>http://www.blogjava.net/mikechen/archive/2012/02/20/370343.html</guid><wfw:comment>http://www.blogjava.net/mikechen/comments/370343.html</wfw:comment><comments>http://www.blogjava.net/mikechen/archive/2012/02/20/370343.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mikechen/comments/commentRss/370343.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mikechen/services/trackbacks/370343.html</trackback:ping><description><![CDATA[<img src="http://www.blogjava.net/images/blogjava_net/mikechen/高级.jpg" border="0" alt="" width="878" height="1545" /><img src ="http://www.blogjava.net/mikechen/aggbug/370343.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mikechen/" target="_blank">陈睿</a> 2012-02-20 14:09 <a href="http://www.blogjava.net/mikechen/archive/2012/02/20/370343.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>