??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲高清成人一区二区三区,亚洲中文无码卡通动漫野外,亚洲成a人片在线看 http://www.tkk7.com/mikechen/category/50933.html电子商务技术架?/description>zh-cn Thu, 20 Jun 2013 08:36:16 GMT Thu, 20 Jun 2013 08:36:16 GMT 60 java classLoader 体系l构 http://www.tkk7.com/mikechen/archive/2013/06/20/400762.html陈睿 陈睿 Thu, 20 Jun 2013 02:25:00 GMT http://www.tkk7.com/mikechen/archive/2013/06/20/400762.html http://www.tkk7.com/mikechen/comments/400762.html http://www.tkk7.com/mikechen/archive/2013/06/20/400762.html#Feedback 0 http://www.tkk7.com/mikechen/comments/commentRss/400762.html http://www.tkk7.com/mikechen/services/trackbacks/400762.html 版权信息 : 可以L转蝲, 转蝲时请务必以超链接形式标明文章原文出处 , 即下面的声明.
原文出处Q?a style="text-decoration: none; color: #0044aa;">http://blog.chenlb.com/2009/06/java-classloader-architecture.html
jvm classLoader architectureQ?/strong>
Bootstrap ClassLoader/启动cd载器 主要负责jdk_home/lib目录下的核心 api ?-Xbootclasspath 选项指定的jar包装入工作?/li> Extension ClassLoader/扩展cd载器 主要负责jdk_home/lib/ext目录下的jar包或 -Djava.ext.dirs 指定目录下的jar包装入工作?/li> System ClassLoader/pȝcd载器 主要负责java -classpath/-Djava.class.path所指的目录下的cMjar包装入工作?/li> User Custom ClassLoader/用户自定义类加蝲?java.lang.ClassLoader的子c? 在程序运行期? 通过java.lang.ClassLoader的子cd态加载class文g, 体现java动态实时类装入Ҏ?/li> cd载器的特性:
每个ClassLoader都维护了一份自q名称I间Q?同一个名U空间里不能出现两个同名的类?/li> Z实现java安全沙箱模型层的类加蝲器安全机? java默认采用?" 双亲委派的加载链 " l构?/li> classloader-architecture
classloader-class-diagram
cd中, BootstrapClassLoader是一个单独的javac, 其实在这里, 不应该叫他是一个javacR因为,它已l完全不用java实现了。它是在jvm启动Ӟ p构造v来的Q?负责javaq_核心库?/p>
自定义类加蝲器加载一个类的步?/strong>
classloader-load-class
ClassLoader cd载逻辑分析Q?以下逻辑是除 BootstrapClassLoader 外的cd载器加蝲程Q?/strong>
// 查类是否已被装蝲q?nbsp; Class c = findLoadedClass(name); if (c == null ) { // 指定cL被装载过 try { if (parent != null ) { // 如果父类加蝲器不为空Q?nbsp;则委z父类加蝲 c = parent.loadClass(name, false ); } else { // 如果父类加蝲器ؓI, 则委z启动cd载加?nbsp; c = findBootstrapClass0(name); } } catch (ClassNotFoundException e) { // 启动cd载器或父cd载器抛出异常后, 当前cd载器其 // 捕获Q?nbsp;q过findClassҎQ?nbsp;pw加?nbsp; c = findClass(name); } } U程上下文类加蝲?/strong> java默认的线E上下文cd载器?pȝcd载器(AppClassLoader)?/p>
// Now create the class loader to use to launch the application try { loader = AppClassLoader.getAppClassLoader(extcl); } catch (IOException e) { throw new InternalError( "Could not create application class loader" ); } // Also set the context class loader for the primordial thread. Thread.currentThread().setContextClassLoader(loader); 以上代码摘自sun.misc.Launch的无参构造函数Launch()?/p>
使用U程上下文类加蝲? 可以在执行线E中, 抛弃双亲委派加蝲链模? 使用U程上下文里的类加蝲器加载类. 典型的例子有, 通过U程上下文来加蝲W三方库jndi实现, 而不依赖于双亲委z? 大部分java app服务?jboss, tomcat..)也是采用contextClassLoader来处理web服务?br />q有一些采?hotswap Ҏ的框架, 也用了U程上下文类加蝲? 比如 seasar (full stack framework in japenese).
U程上下文从Ҏ解决了一般应用不能违背双亲委z模式的问题. 使javacd载体pL得更灉|.
随着多核时代的来? 怿多线E开发将会越来越多地q入E序员的实际~码q程? 因此, 在编写基设施Ӟ 通过使用U程上下文来加蝲c? 应该是一个很好的选择?/p>
当然, 好东襉K有利? 使用U程上下文加载类, 也要注意, 保证多根需要通信的线E间的类加蝲器应该是同一? 防止因ؓ不同的类加蝲? Dcd转换异常(ClassCastException)?/p>
Z么要使用q种双亲委托模式呢?
因ؓq样可以避免重复加蝲Q当父亲已经加蝲了该cȝ时候,没有必要子ClassLoader再加载一ơ?/li> 考虑到安全因素,我们试想一下,如果不用这U委托模式,那我们就可以随时使用自定义的String来动态替代java核心api中定义类型,q样会存在非常大的安全隐患,而双亲委托的方式Q就可以避免q种情况Q因为String已经在启动时被加载,所以用戯定义cL无法加蝲一个自定义的ClassLoader?/li> java动态蝲入class的两U方式:
implicit隐式,卛_用实例化才蝲入的Ҏ来动态蝲入class explicit昑ּ方式,又分两种方式:java.lang.Class的forName()Ҏ java.lang.ClassLoader的loadClass()Ҏ 用Class.forName加蝲c?/strong>
Class.forName使用的是被调用者的cd载器来加载类的?br />q种Ҏ? 证明了javacd载器中的名称I间是唯一? 不会怺q扰?br />卛_一般情况下, 保证同一个类中所兌的其他类都是由当前类的类加蝲器所加蝲的?/p>
public static Class forName(String className) throws ClassNotFoundException { return forName0(className, true , ClassLoader.getCallerClassLoader()); } /** Called after security checks have been made. */ private static native Class forName0(String name, boolean initialize, ClassLoader loader) throws ClassNotFoundException; 上面?ClassLoader.getCallerClassLoader 是得到调用当前forNameҎ的类的类加蝲?/p>
static块在什么时候执?
当调用forName(String)载入class时执?如果调用ClassLoader.loadClassq不会执?forName(String,false,ClassLoader)时也不会执行. 如果载入Class时没有执行static块则在第一ơ实例化时执?比如new ,Class.newInstance()操作 static块仅执行一?/li> 各个javacȝ哪些classLoader加蝲?
javacd以通过实例.getClass.getClassLoader()得知 接口由AppClassLoader(System ClassLoader,可以由ClassLoader.getSystemClassLoader()获得实例)载入 ClassLoadercȝbootstrap loader载入 NoClassDefFoundError和ClassNotFoundException
NoClassDefFoundError:当java源文件已~译?class文g,但是ClassLoader在运行期间在其搜寻\径load某个cL,没有扑ֈ.class文g则报q个?/li> ClassNotFoundException:试图通过一个String变量来创Z个ClasscL不成功则抛出q个异常
]]>事务 http://www.tkk7.com/mikechen/archive/2012/06/11/380502.html陈睿 陈睿 Mon, 11 Jun 2012 07:46:00 GMT http://www.tkk7.com/mikechen/archive/2012/06/11/380502.html http://www.tkk7.com/mikechen/comments/380502.html http://www.tkk7.com/mikechen/archive/2012/06/11/380502.html#Feedback 0 http://www.tkk7.com/mikechen/comments/commentRss/380502.html http://www.tkk7.com/mikechen/services/trackbacks/380502.html 事务必须服从ISO/IEC所制定的ACID原则。ACID是原子性(atomicityQ、一致性(consistencyQ、隔L(isolationQ和持久性(durabilityQ的~写 事务的原子性:表示事务执行q程中的Mp|都将D事务所做的M修改失效?/span> 一致性表C当事务执行p|Ӟ所有被该事务媄响的数据都应该恢复到事务执行前的状态?/span>
隔离性表C在事务执行q程中对数据的修改,在事务提交之前对其他事务不可见?br /> 持久性表C已提交的数据在事务执行p|Ӟ数据的状态都应该正确?nbsp; 二:事务的场?br /> 1.与银行相关的业务Q重要的数据Q与q关的内容不能ZQ何错?br /> 2.pȝ内部认ؓ重要的数据,都需要事务的支持Q防止重要数据的不一致?br /> 3.具体的业务场景:银行业务Q支付业务,交易业务{?br /> 三:事务的实现方?br /> 首先说一下事务的cdQ主要包含一下三U:JDBC事务QJTA事务Q容器事?br /> 1、JDBC事务 JDBC 事务是用 Connection 对象控制的。JDBC Connection 接口( java.sql.Connection )提供了两U事务模式:自动提交和手工提交?java.sql.Connection 提供了以下控制事务的ҎQ?nbsp; public void setAutoCommit(boolean) public boolean getAutoCommit() public void commit() public void rollback() 使用 JDBC 事务界定Ӟ您可以将多个 SQL 语句l合C个事务中。JDBC 事务的一个缺Ҏ事务的范围局限于一个数据库q接。一?JDBC 事务不能跨越多个数据库?nbsp; 2、JTA(Java Transaction API)事务 JTA是一U高层的Q与实现无关的,与协议无关的APIQ应用程序和应用服务器可以用JTA来访问事务?nbsp; JTA允许应用E序执行分布式事务处?-在两个或多个|络计算源上讉Kq且更新数据Q这些数据可以分布在多个数据库上。JDBC驱动E序的JTA支持极大地增Z数据讉K能力?nbsp; 如果计划?JTA 界定事务Q那么就需要有一个实?javax.sql.XADataSource ?javax.sql.XAConnection ?javax.sql.XAResource 接口?JDBC 驱动E序。一个实Cq些接口的驱动程序将可以参与 JTA 事务。一?XADataSource 对象是一?XAConnection 对象的工厂?XAConnection s 是参?JTA 事务?JDBC q接?nbsp; 您将需要用应用服务器的理工具讄 XADataSource 。从应用服务器和 JDBC 驱动E序的文档中可以了解到相关的指导?nbsp; J2EE 应用E序?JNDI 查询数据源。一旦应用程序找C数据源对象,它就调用 javax.sql.DataSource.getConnection() 以获得到数据库的q接?nbsp; XA q接与非 XA q接不同。一定要C XA q接参与?JTA 事务。这意味着 XA q接不支?JDBC 的自动提交功能。同Ӟ应用E序一定不要对 XA q接调用 java.sql.Connection.commit() 或?java.sql.Connection.rollback() 。相反,应用E序应该使用 UserTransaction.begin()?UserTransaction.commit() ?serTransaction.rollback() ?nbsp; 3、容器事?nbsp; 容器事务主要是J2EE应用服务器提供的Q容器事务大多是ZJTA完成Q这是一个基于JNDI的,相当复杂的API实现。相对编码实现JTA事务理Q我们可以通过EJB容器提供的容器事务管理机ӞCMTQ完成同一个功能,q项功能由J2EE应用服务器提供。这使得我们可以单的指定哪个方法加入事务,一旦指定,容器负责事务管理Q务。这是我们土建的解决方式Q因为通过q种方式我们可以事务代码排除在逻辑~码之外Q同时将所有困难交lJ2EE容器去解冟뀂用EJB CMT的另外一个好处就是程序员无需兛_JTA API的编码,不过Q理Z我们必须使用EJB?nbsp; 四、三U事务差?nbsp; 1、JDBC事务控制的局限性在一个数据库q接内,但是其用简单?nbsp; 2、JTA事务的功能强大,事务可以跨越多个数据库或多个DAOQ用也比较复杂?nbsp; 3、容器事务,主要指的是J2EE应用服务器提供的事务理Q局限于EJB应用使用?nbsp; 五:详解事务 1.首先看一下目前用最多的spring事务Q目前spring配置分ؓ声明式事务和~程式事务?br /> 1Q编E式事务 主要是实现接口PlatformTransactionManager 实现了事务管理的接口有非常多Q这里主要讲DataSourceTransactionManager和数据库jdbc相关的事务处理方?img src ="http://www.tkk7.com/mikechen/aggbug/380502.html" width = "1" height = "1" /> ]]> java虚拟?/title> http://www.tkk7.com/mikechen/archive/2012/02/27/370847.html陈睿 陈睿 Mon, 27 Feb 2012 07:35:00 GMT http://www.tkk7.com/mikechen/archive/2012/02/27/370847.html http://www.tkk7.com/mikechen/comments/370847.html http://www.tkk7.com/mikechen/archive/2012/02/27/370847.html#Feedback 1 http://www.tkk7.com/mikechen/comments/commentRss/370847.html http://www.tkk7.com/mikechen/services/trackbacks/370847.html JVM specification对JVM内存的描q?/span>
首先我们来了解JVM specification中的JVM整体架构。如下图Q?/p>
主要包括两个子系l和两个lgQ?/span> Class loader( c装载器 ) 子系l, Execution engine( 执行引擎 ) 子系l; Runtime data area ( q行时数据区?/span>) lgQ?/span> Native interface( 本地接口 ) lg?/span> Class loader 子系l的作用 Q根据给定的全限定名cd ( ?/span> java.lang.Object) 来装?/span>class 文g的内容到 Runtime data area 中的 method area( Ҏ区域 ) ?/span>Javsa E序员可?/span>extends java.lang.ClassLoader cL写自q Class loader ?/span> Execution engine 子系l的作用 Q执?/span>classes 中的指o。Q?/span>JVM specification 实现 (JDK) 的核心是 Execution engine Q?/span> 换句话说Q?/span>Sun ?/span>JDK ?/span>IBM ?/span>JDK 好坏主要取决于他们各自实现的 Execution engine 的好坏。每个运行中的线E都有一?/span>Execution engine 的实例?/span> Native interface lg Q与 native libraries 交互Q是其它~程语言交互的接口?/span> Runtime data area lgQ这个组件就?/span>JVM 中的内存 Runtime data area 主要包括五个部分QHeap (?, Method Area(Ҏ区域), Java Stack(java的栈), Program Counter(E序计数?, Native method stack(本地Ҏ?。Heap 和Method Area是被所有线E的׃n使用的;而Java stack, Program counter 和Native method stack是以U程为粒度的Q每个线E独自拥有?/span> Heap JavaE序在运行时创徏的所有类实或数组都放在同一个堆中?/span>而一?span>Java虚拟实例中只存在一个堆I间Q因此所有线E都共享这个堆。每一个javaE序独占一个JVM实例Q因而每个javaE序都有它自q堆空_它们不会彼此q扰。但是同一javaE序的多个线E都׃n着同一个堆I间Q就得考虑多线E访问对象(堆数据)的同步问题? Q这里可能出现的异常java.lang.OutOfMemoryError: Java heap spaceQ?/span>
JVM堆一般又可以分ؓ以下三部分:
Ø Perm
Perm代主要保?/span>class,method,filed 对象Q这部门的空间一般不会溢出,除非一ơ性加载了很多的类Q不q在涉及到热部v的应用服务器的时候,有时候会遇到 java.lang.OutOfMemoryError : PermGen space 的错误,造成q个错误的很大原因就有可能是每次都重新部|Ԍ但是重新部v后,cȝ class 没有被卸载掉Q这样就造成了大量的 class 对象保存在了 perm 中,q种情况下,一般重新启动应用服务器可以解决问题?/span>
Ø Tenured
TenuredZ要保存生命周期长的对象,一般是一些老的对象Q当一些对象在 Young 复制转移一定的ơ数以后Q对象就会被转移?/span>Tenured 区,一般如果系l中用了 application U别的缓存,~存中的对象往往会被转移到这一区间?/span>
Ø Young
Young 划分Z部分Q?/span>Eden 区和两个大小严格相同?/span>Survivor 区,其中 Survivor 区间中,某一时刻只有其中一个是被用的Q另外一个留做垃圾收集时复制对象用,?/span>Young 区间变满的时候, minor GC ׃存zȝ对象UdI闲?/span>Survivor 区间中,Ҏ JVM 的策略,在经q几ơ垃圾收集后QQ然存zM Survivor 的对象将被移动到 Tenured 区间?/span>
Method area 在Java虚拟ZQ被装蝲的class的信息存储在Method area的内存中?/span>当虚拟机装蝲某个cdӞ它用类装蝲器定位相应的class文gQ然后读入这个class文g内容q把它传输到虚拟Z。紧接着虚拟机提取其中的cd信息Qƈ这些信息存储到Ҏ区。该cd中的c(静态)变量同样也存储在ҎZ。与Heap 一Pmethod area是多U程׃n的,因此要考虑多线E访问的同步问题。比如,假设同时两个U程都企图访问一个名为Lava的类Q而这个类q没有内装蝲入虚拟机Q那么,q时应该只有一个线E去装蝲它,而另一个线E则只能{待? Q这里可能出现的异常java.lang.OutOfMemoryError: PermGen fullQ?br /> Java stack Java stack以为单位保存线E的q行状态。虚拟机只会直接对Java stack执行两种操作Q以帧ؓ单位的压栈或出栈?/span>每当U程调用一个方法的时候,对当前状态作Z个保存?span>java stack?压栈)Q当一个方法调用返回时Q从java stack弹出一个(出栈)?span style="color:red">栈的大小是有一定的限制Q这个可能出现StackOverFlow问题?/span> 下面的程序可以说明这个问题?p>
public class TestStackOverFlow { public static void main(String[] args) { Recursive r = new Recursive(); r.doit(10000); // Exception in thread "main" java.lang.StackOverflowError } } class Recursive { public int doit(int t) { if (t <= 1) { return 1; } return t + doit(t - 1); } } Program counter 每个q行中的 JavaE序Q每一个线E都有它自己?/span>PC寄存器,也是该线E启动时创徏的?/span>PC寄存器的内容L指向下一条将被执行指令的?/span>“地址 ”Q这里的 “地址 ”可以是一个本地指针,也可以是在方法区中相对应于该Ҏ起始指o的偏U量?/span> Native method stack 对于一个运行中?/span>JavaE序而言Q它q能会用C些跟本地Ҏ相关的数据区。当某个U程调用一个本地方法时Q它p入了一个全新的q且不再受虚拟机限制的世界。本地方法可以通过本地Ҏ接口来访问虚拟机的运行时数据区,不止与此Q它q可以做M它想做的事情。比如,可以调用寄存器,或在操作pȝ中分配内存等。MQ本地方法具有和 JVM相同的能力和权限?/span> ( q里出现 JVM 无法控制的内存溢出问?/span>native heap OutOfMemory ) JVM提供了相应的参数来对内存大小q行配置?br />
正如上面描述Q?/span>JVM 中堆被分Z 3 个大的区_同时 JVM 也提供了一些选项?/span>Young,Tenured 的大进行控制?/span>
Ø Total Heap
-Xms Q指定了 JVM 初始启动以后初始化内?/span>
-Xmx Q指?/span>JVM 堆得最大内存,?/span>JVM 启动以后Q会分配 -Xmx 参数指定大小的内存给 JVM Q但是不一定全部用, JVM 会根?/span>-Xms 参数来调节真正用?/span>JVM 的内?/span>
-Xmx -Xms之差是三个 Virtual I间的大?/span>
Ø Young Generation
-XX:NewRatio=8意味着 tenured ?/span> young 的比?/span>8 Q?/span>1 Q这?/span>eden+2*survivor=1/9
堆内?/span>
-XX:SurvivorRatio=32意味着 eden 和一?/span>survivor 的比值是 32 Q?/span>1 Q这样一?/span>Survivor 占 Young 区的 1/34.
-Xmn 参数讄了年M的大?/span>
Ø Perm Generation
-XX:PermSize= 16 M -XX:MaxPermSize= 64 M
Thread Stack
-XX:Xss=128K
]]>多线E?/title> http://www.tkk7.com/mikechen/archive/2012/02/21/370416.html陈睿 陈睿 Tue, 21 Feb 2012 07:32:00 GMT http://www.tkk7.com/mikechen/archive/2012/02/21/370416.html http://www.tkk7.com/mikechen/comments/370416.html http://www.tkk7.com/mikechen/archive/2012/02/21/370416.html#Feedback 0 http://www.tkk7.com/mikechen/comments/commentRss/370416.html http://www.tkk7.com/mikechen/services/trackbacks/370416.html 1. 多线E概念: U程是指q程中的一个执行流E,一个进E中可以q行多个U程。比如java.exeq程中可以运行很多线E。线EL属于某个q程Q进E中的多个线E共享进E的内存?ul> 多线E的实现方式和启?/li> 多线E是依靠什么方式解册源竞?/li> 多线E的各种状态以及优先 多线E的暂停方式 2. 多线E详?/strong> 1Q多U程的实现方式和启动: l承Thread和是实现Runnable接口Q重写runҎ 启动只有一U方式:通过startҎQ虚拟机会调用runҎ 2Q?多线E依靠什么解册源竞?/strong> 锁机Ӟ分ؓ对象锁和c锁Q在多个U程调用的情况,每个对象锁都是唯一的,只有获取了锁才能调用synchronizedҎ synchronize同步Q分为同步方法和同步Ҏ?/li> 什么时候获取锁Q每ơ调用到synchronizeҎQ这个时候去获取锁资源,如果U程获取到锁则别的线E只有等到同步方法介l后Q释N后,别的U程 才能l箋使用 3Q线E的几种状?/strong> 主要分ؓQ新状态(q没有调用startҎQ,可执行状态(调用startҎQ,d状态,M状?/li> 默认优先Uؓnormal(5),优先U数值在1-10之间 4) 多线E的暂停方式 sleep:睡眠单位为毫U?/li> wait,waitAll,notify,notifyAll,wait{待Q只有通过wait或者waitAll唤醒 yieldQcpu暂时停用 join ]]> 容器-Set-HashSet http://www.tkk7.com/mikechen/archive/2012/02/21/370398.html陈睿 陈睿 Tue, 21 Feb 2012 03:37:00 GMT http://www.tkk7.com/mikechen/archive/2012/02/21/370398.html http://www.tkk7.com/mikechen/comments/370398.html http://www.tkk7.com/mikechen/archive/2012/02/21/370398.html#Feedback 0 http://www.tkk7.com/mikechen/comments/commentRss/370398.html http://www.tkk7.com/mikechen/services/trackbacks/370398.html HashSet概要 Q?/li> 采用HashMap存储Qkey直接存取|value存储一个object 存储的key值是唯一?/li> HashSet中元素的序是随机的Q包括添?add())和输出都是无序的代码׃具体详解了,主要是通过装HashMapl成?/strong>
]]>容器-Map-Hashtable http://www.tkk7.com/mikechen/archive/2012/02/21/370390.html陈睿 陈睿 Tue, 21 Feb 2012 02:32:00 GMT http://www.tkk7.com/mikechen/archive/2012/02/21/370390.html http://www.tkk7.com/mikechen/comments/370390.html http://www.tkk7.com/mikechen/archive/2012/02/21/370390.html#Feedback 0 http://www.tkk7.com/mikechen/comments/commentRss/370390.html http://www.tkk7.com/mikechen/services/trackbacks/370390.html 1.Hashtable概要Q实现Map接口的同步实?/strong> U程安全 不能存储null到key和value HashTable中hash数组默认大小?1Q增加的方式?old*2+1。HashMap中hash数组的默认大是16Q而且一定是2的指?br />区别
Hashtable
Hashmap
l承、实?/p>
Hashtable extends Dictionaryimplements Map, Cloneable,Serializable
HashMap extends AbstractMap implements Map, Cloneable,Serializable
U程同步
已经同步q的可以安全使用
未同步的Q可以用Colletcionsq行同步Map Collections.synchronizedMap(Map m)
对null的处?/p>
Hashtable table = new Hashtable();
table.put(null, "Null");
table.put("Null", null);
table.contains(null);
table.containsKey(null);
table.containsValue(null);
后面?句话在编译的时候不会有异常Q可在运行的时候会报空指针异常具体原因可以查看源代?/p>
public synchronized V put(K key, V value) {
// Make sure the value is not null
if (value == null) {
throw new NullPointerException();
}
HashMap map = new HashMap(); map.put(null, "Null");
map.put("Null", null);
map.containsKey(null);
map.containsValue(null);
以上q?条语句无论在~译期,q是在运行期都是没有错误?
在HashMap中,null可以作ؓ键,q样的键只有一个;可以有一个或多个键所对应的gؓnull。当get()Ҏq回null值时Q即可以表示 HashMap中没有该键,也可以表C键所对应的gؓnull。因此,在HashMap中不能由get()Ҏ来判断HashMap中是否存在某个键Q而应该用containsKey()Ҏ来判断?/p>
增长?/p>
protected void rehash() {
int oldCapacity = table.length;
Entry[] oldMap = table;
int newCapacity = oldCapacity * 2 + 1;
Entry[] newMap = new Entry[newCapacity];
modCount++;
threshold = (int)(newCapacity * loadFactor);
table = newMap;
for (int i = oldCapacity ; i-- > 0 ;) {
for (Entry old = oldMap[i] ; old != null ; ) {
Entry e = old;
old = old.next;
int index = (e.hash & 0x7FFFFFFF) % newCapacity;
e.next = newMap[index];
newMap[index] = e;
}
}
}
void addEntry(int hash, K key, V value, int bucketIndex) {
Entry e = table[bucketIndex];
table[bucketIndex] = new Entry(hash, key, value, e);
if (size++ >= threshold)
resize(2 * table.length);
}
哈希值的使用
HashTable直接使用对象的hashCodeQ代码是q样的:
public synchronized boolean containsKey(Object key) {
Entry tab[] = table;
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
for (Entry e = tab[index] ; e !=null ; e = e.next) {
if ((e.hash == hash) && e.key.equals(key)) {
return true ;
}
}
return false ;
}
HashMap重新计算hash|而且用与代替求模
public boolean containsKey(Object key) {
Object k = maskNull(key);
int hash = hash(k.hashCode());
int i = indexFor(hash, table.length);
Entry e = table[i];
while (e != null) {
if (e.hash == hash && eq(k, e.key))
return true;
e = e.next;
}
return false;
}
]]> 容器-Map-HashMap http://www.tkk7.com/mikechen/archive/2012/02/20/370353.html陈睿 陈睿 Mon, 20 Feb 2012 08:40:00 GMT http://www.tkk7.com/mikechen/archive/2012/02/20/370353.html http://www.tkk7.com/mikechen/comments/370353.html http://www.tkk7.com/mikechen/archive/2012/02/20/370353.html#Feedback 0 http://www.tkk7.com/mikechen/comments/commentRss/370353.html http://www.tkk7.com/mikechen/services/trackbacks/370353.html 1. HashMap概要Q基于哈希表Map接口的非同步实现 U程不安?U程安全请用Hashtable 效率较好 提供null作ؓkey或者value 2. HashMap代码详解 Q?br /> /** * Constructs an empty <tt>HashMap</tt> with the default initial capacity * (16) and the default load factor (0.75). */ public HashMap() { this .loadFactor = DEFAULT_LOAD_FACTOR; //默认?.75 threshold = ( int )(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); //扩容的门槛,存入的数据大于该|定w扩充一?/strong> table = new Entry[DEFAULT_INITIAL_CAPACITY]; //初始化数l,数组内容为EntryQ存储链?/strong> init();
public V put(K key, V value) { if (key == null ) return putForNullKey(value); //如果key为nullQ直接把value攑ֈ数组W一位table[0] int hash = hash(key.hashCode()); //通过可以的hashcode计算对应的hash?/strong> int i = indexFor(hash, table.length); //通过hash|把entry对应到数l的位数计算出来 for (Entry < K,V > e = table[i]; e != null ; e = e.next) { //如果该entryq包含下一个entry的引用,则l遍历该链表 Object k;if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { //如果key相同Q则替换新的value到制定的key V oldValue = e.value; e.value = value; e.recordAccess( this ); return oldValue; } } modCount ++ ; addEntry(hash, key, value, i); return null ; }
public V get(Object key) { if (key == null ) //key为nullQ直接从数组W一位拿数据 return getForNullKey(); int hash = hash(key.hashCode()); for (Entry < K,V > e = table[indexFor(hash, table.length)]; //直接通过key的hashcode计算出对应到数组的烦引位Q直接取数据Q如果有链表l箋查找 e != null ; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) return e.value; } return null ; }
HashMap别的Ҏ׃l箋详解了,主要通过put与get可以很好的理解HashMap底层的结构,以及工作方式?br /> ]]> 容器-数组-Vector http://www.tkk7.com/mikechen/archive/2012/02/20/370351.html陈睿 陈睿 Mon, 20 Feb 2012 08:11:00 GMT http://www.tkk7.com/mikechen/archive/2012/02/20/370351.html http://www.tkk7.com/mikechen/comments/370351.html http://www.tkk7.com/mikechen/archive/2012/02/20/370351.html#Feedback 0 http://www.tkk7.com/mikechen/comments/commentRss/370351.html http://www.tkk7.com/mikechen/services/trackbacks/370351.html 1. Vector概要Q?/strong> /** * Constructs an empty vector so that its internal data array * has size { @code 10} and its standard capacity increment is * zero. */ public Vector() { this ( 10 ); }
底层采用数组存储 Q?span class="Apple-style-span" style="font-size: 13px; ">protected Object[] elementData; U程安全 查询效率比较高,比较适用于查?/strong> 扩容的长度ؓ初始长度的一半,初始化的时候设|已知的长度Q免得容器自己去扩容Q浪费空间以及效?br />与ArrayList基本一P除了所有操作资源的Ҏ都加?/strong>synchronizedQ保证线E同?br />q里的源代码׃详解了,具体请参?a href="http://www.tkk7.com/mikechen/articles/370346.html" title="容器-数组-ArrayList详解">容器-数组-ArrayList详解?/li> ]]> 容器-数组-ArrayList http://www.tkk7.com/mikechen/archive/2012/02/20/370346.html陈睿 陈睿 Mon, 20 Feb 2012 06:28:00 GMT http://www.tkk7.com/mikechen/archive/2012/02/20/370346.html http://www.tkk7.com/mikechen/comments/370346.html http://www.tkk7.com/mikechen/archive/2012/02/20/370346.html#Feedback 0 http://www.tkk7.com/mikechen/comments/commentRss/370346.html http://www.tkk7.com/mikechen/services/trackbacks/370346.html 1. ArrayList概要Q?/strong> public ArrayList() { this ( 10 ); }
底层采用数组存储 Q?span class="Apple-style-span" style="font-size: 13px; ">private transient Object[] elementData; transient表示数组elementData不需要通过serialization序列化传?br />U程不安全,在多U程场景会出现问题,可以考虑使用Vector或者Collections.synchronizedList同步该容?/strong> 查询效率比较高,比较适用于查?/strong> 扩容的长度ؓ初始长度的一半,初始化的时候设|已知的长度Q免得容器自己去扩容Q浪费空间以及效?/strong> 2. ArrayList代码详解Q?/strong> public boolean add(E e) { ensureCapacity(size + 1 ); // Increments modCount!! elementData[size ++ ] = e; return true ; }
首先查数l是否已满,如果满了开始扩容,扩容后的长度为原长度?.5倍?span class="Apple-style-span" style="font-size: 13px; ">/** * Increases the capacity of this <tt>ArrayList</tt> instance, if * necessary, to ensure that it can hold at least the number of elements * specified by the minimum capacity argument. * * @param minCapacity the desired minimum capacity */ public void ensureCapacity( int minCapacity) { modCount ++ ;//modCount表示数组的操作计敎ͼ用于iterator的时候与 Count比较Q防止P代操作对add,remove{操作媄响P代操?/span> int oldCapacity = elementData.length; if (minCapacity > oldCapacity) { //新插入元素后的长度大于老的长度Q数l开始扩?/span> Object oldData[] = elementData; int newCapacity = (oldCapacity * 3 ) / 2 + 1 ; //新空间ؓ原长度的1.5倍,{于是扩容了50% if (newCapacity < minCapacity) newCapacity = minCapacity; // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); //把之前的元素拯到新的数l?nbsp; } } /** * Removes the element at the specified position in this list. * Shifts any subsequent elements to the left (subtracts one from their * indices). * * @param index the index of the element to be removed * @return the element that was removed from the list * @throws IndexOutOfBoundsException { @inheritDoc } */ public E remove( int index) { RangeCheck(index); //查烦引是否溢?br /> modCount ++ ; //操作计数 E oldValue = (E) elementData[index]; int numMoved = size - index - 1 ; if (numMoved > 0 ) System.arraycopy(elementData, index + 1 , elementData, index,//复制原数l制定index+1到length-1的元素到elementData的index的烦引位 numMoved); elementData[ -- size] = null ; // Let gc do its work//最后一位设|ؓnull return oldValue; }
/** * Checks if the given index is in range. If not, throws an appropriate * runtime exception. This method does *not* check if the index is * negative: It is always used immediately prior to an array access, * which throws an ArrayIndexOutOfBoundsException if index is negative. */ private void RangeCheck( int index) { if (index >= size) throw new IndexOutOfBoundsException( " Index: " + index + " , Size: " + size); }
/** * Returns the element at the specified position in this list. * * @param index index of the element to return * @return the element at the specified position in this list * @throws IndexOutOfBoundsException { @inheritDoc } */ public E get( int index) { RangeCheck(index); return (E) elementData[index]; //直接获取数组的烦引位 }
]]> java高知识概要 http://www.tkk7.com/mikechen/archive/2012/02/20/370343.html陈睿 陈睿 Mon, 20 Feb 2012 06:09:00 GMT http://www.tkk7.com/mikechen/archive/2012/02/20/370343.html http://www.tkk7.com/mikechen/comments/370343.html http://www.tkk7.com/mikechen/archive/2012/02/20/370343.html#Feedback 0 http://www.tkk7.com/mikechen/comments/commentRss/370343.html http://www.tkk7.com/mikechen/services/trackbacks/370343.html ]]>
վ֩ģ壺
Ƶ97Ӱ |
һƬɫ |
þùһƬѹۿ |
24Сʱձ |
һ߹ۿ |
avr |
Ļһȥ̨
|
ѿֻվ
|
ƷӰ߹ۿ |
þƷĻ |
Ƶ |
Ƶѿ |
ëƬavպav |
С˵ͼƬ |
72paoƵ |
ѹ߹ۿ |
Ļ |
Ʒһ |
91Ʒѹۿ |
ƷƵ߹ۿ |
Ʒþþþ |
ƷѸ߹ۿ |
˳߹ۿƵ |
Ʒ˿߹ۿ |
ڵֻˬվ |
ձ |
ͬgayվ߹ۿ |
wwwѸƵ |
ƷѵĻվ |
ƷۺϾþþ |
߹ۿƬڲ |
һѹۿ |
ҹ |
þþþƷƵ |
˾ƷƷ |
sŷm봵 |
ѳ˼Ƶ |
컶ëƬ |
ɫѹۿ |
˳߹ۿŹ |
|