java中Conjava currenthashmapp不能被加锁来执行独占访问??

非线程安全的HashMap&和&线程安全的ConcurrentHashMap
在平时开发中,我们经常采用HashMap来作为本地缓存的一种实现方式,将一些如系统变量等数据量比较少的参数保存在HashMap中,并将其作
为单例类的一个属性。在系统运行中,使用到这些缓存数据,都可以直接从该单例中获取该属性集合。但是,最近发现,HashMap并不是线程安全的,如果你
的单例类没有做代码同步或对象锁的控制,就可能出现异常。
首先看下在多线程的访问下,非现场安全的HashMap的表现如何,在网上看了一些资料,自己也做了一下测试:
&1<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" ALIGN="top" NAME="Codehighlighter1_23_869_Open_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" /><img STYLE="display:" ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" ALIGN="top" NAME="Codehighlighter1_23_869_Closed_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />public&class&MainClass&<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/dot.gif"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />{&2<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&
&3<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&public&static&final&HashMap&String,&String&&firstHashMap=new&HashMap&String,&String&();
&4<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&
&5<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" ALIGN="top" NAME="Codehighlighter1_186_866_Open_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" /><img STYLE="display:" ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" ALIGN="top" NAME="Codehighlighter1_186_866_Closed_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&public&static&void&main(String[]&args)&throws&InterruptedException&<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/dot.gif"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />{&6<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&
&7<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&//线程一
&8<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" ALIGN="top" NAME="Codehighlighter1_223_349_Open_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" /><img STYLE="display:" ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" ALIGN="top" NAME="Codehighlighter1_223_349_Closed_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&Thread&t1=new&Thread()<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/dot.gif"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />{&9<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" ALIGN="top" NAME="Codehighlighter1_246_345_Open_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" /><img STYLE="display:" ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" ALIGN="top" NAME="Codehighlighter1_246_345_Closed_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&public&void&run()&<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/dot.gif"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />{10<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" ALIGN="top" NAME="Codehighlighter1_273_340_Open_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" /><img STYLE="display:" ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" ALIGN="top" NAME="Codehighlighter1_273_340_Closed_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&&&&&for(int&i=0;i&25;i++)<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/dot.gif"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />{11<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&&&&&&&&&firstHashMap.put(String.valueOf(i),&String.valueOf(i));
12<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&&&&&}
13<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&}
14<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&};
15<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&
16<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&//线程二
17<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" ALIGN="top" NAME="Codehighlighter1_387_514_Open_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" /><img STYLE="display:" ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" ALIGN="top" NAME="Codehighlighter1_387_514_Closed_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&Thread&t2=new&Thread()<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/dot.gif"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />{18<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" ALIGN="top" NAME="Codehighlighter1_410_510_Open_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" /><img STYLE="display:" ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" ALIGN="top" NAME="Codehighlighter1_410_510_Closed_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&public&void&run()&<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/dot.gif"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />{19<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" ALIGN="top" NAME="Codehighlighter1_438_505_Open_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" /><img STYLE="display:" ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" ALIGN="top" NAME="Codehighlighter1_438_505_Closed_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&&&&&for(int&j=25;j&50;j++)<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/dot.gif"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />{20<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&&&&&&&&&firstHashMap.put(String.valueOf(j),&String.valueOf(j));
21<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&&&&&}
22<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&}
23<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&};
24<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&
25<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&t1.start();
26<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&t2.start();
27<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&
28<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&//主线程休眠1秒钟,以便t1和t2两个线程将firstHashMap填装完毕。
29<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&Thread.currentThread().sleep(1000);
30<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&
31<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" ALIGN="top" NAME="Codehighlighter1_658_860_Open_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" /><img STYLE="display:" ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" ALIGN="top" NAME="Codehighlighter1_658_860_Closed_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&for(int&l=0;l&50;l++)<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/dot.gif"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />{32<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&//如果key和value不同,说明在两个线程put的过程中出现异常。
33<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" ALIGN="top" NAME="Codehighlighter1_768_856_Open_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" /><img STYLE="display:" ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" ALIGN="top" NAME="Codehighlighter1_768_856_Closed_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&if(!String.valueOf(l).equals(firstHashMap.get(String.valueOf(l))))<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/dot.gif"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />{34<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&&&&&System.err.println(String.valueOf(l)+":"+firstHashMap.get(String.valueOf(l)));
35<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&}
36<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&}
37<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&
38<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&}
39<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />40<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />}
上面的代码在多次执行后,发现表现很不稳定,有时没有异常文案打出,有时则有个异常出现:
<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/images/blogjava_net/lukangping/.GIF" BORDER="0"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />
为什么会出现这种情况,主要看下HashMap的实现:
&1<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" ALIGN="top" NAME="Codehighlighter1_29_581_Open_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" /><img STYLE="display:" ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" ALIGN="top" NAME="Codehighlighter1_29_581_Closed_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />public&V&put(K&key,&V&value)&<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/dot.gif"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />{&2<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&if&(key&==&null)
&3<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&return&putForNullKey(value);
&4<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&int&hash&=&hash(key.hashCode());
&5<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&int&i&=&indexFor(hash,&table.length);
&6<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" ALIGN="top" NAME="Codehighlighter1_231_494_Open_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" /><img STYLE="display:" ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" ALIGN="top" NAME="Codehighlighter1_231_494_Closed_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&for&(Entry&K,V&&e&=&table[i];&e&!=&null;&e&=&e.next)&<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/dot.gif"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />{&7<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&Object&k;
&8<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" ALIGN="top" NAME="Codehighlighter1_328_484_Open_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" /><img STYLE="display:" ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" ALIGN="top" NAME="Codehighlighter1_328_484_Closed_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&if&(e.hash&==&hash&&&&((k&=&e.key)&==&key&||&key.equals(k)))&<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/dot.gif"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />{&9<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&&&&&V&oldValue&=&e.
10<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&&&&&e.value&=&
11<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&&&&&e.recordAccess(this);
12<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&&&&&return&oldV
13<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&}
14<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&}
15<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />16<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&modCount++;
17<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&addEntry(hash,&key,&value,&i);
18<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&return&null;
19<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&}
我觉得问题主要出现在方法addEntry,继续看:
1<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" ALIGN="top" NAME="Codehighlighter1_57_236_Open_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" /><img STYLE="display:" ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" ALIGN="top" NAME="Codehighlighter1_57_236_Closed_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />void&addEntry(int&hash,&K&key,&V&value,&int&bucketIndex)&<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/dot.gif"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />{2<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&Entry&K,V&&e&=&table[bucketIndex];
3<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&table[bucketIndex]&=&new&Entry&K,V&(hash,&key,&value,&e);
4<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&if&(size++&&=&threshold)
5<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&resize(2&*&table.length);
6<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&}
从代码中,可以看到,如果发现哈希表的大小超过阀值threshold,就会调用resize方法,扩大容量为原来的两倍,而扩大容量的做法是新建一个
&1<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" ALIGN="top" NAME="Codehighlighter1_29_391_Open_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" /><img STYLE="display:" ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" ALIGN="top" NAME="Codehighlighter1_29_391_Closed_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />void&resize(int&newCapacity)&<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/dot.gif"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />{&2<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&Entry[]&oldTable&=&
&3<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&int&oldCapacity&=&oldTable.
&4<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" ALIGN="top" NAME="Codehighlighter1_153_226_Open_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" /><img STYLE="display:" ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" ALIGN="top" NAME="Codehighlighter1_153_226_Closed_Image"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&if&(oldCapacity&==&MAXIMUM_CAPACITY)&<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/dot.gif"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />{&5<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&threshold&=&Integer.MAX_VALUE;
&6<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&&&&&return;
&7<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&}
&8<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&9<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&Entry[]&newTable&=&new&Entry[newCapacity];
10<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&transfer(newTable);
11<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&table&=&newT
12<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&&&&&threshold&=&(int)(newCapacity&*&loadFactor);
13<img ALT="" src="/blog7style/images/common/sg_trans.gif" real_src ="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" ALIGN="top"
TITLE="非线程安全的HashMap&和&线程安全的ConcurrentHashMap" />&&&&}
一般我们声明HashMap时,使用的都是默认的构造方法:HashMap&K,V&,看了代码你会发现,它还有其它的构造方法:HashMap(int
initialCapacity, float loadFactor),其中参数initialCapacity为初始容
量,loadFactor为加载因子,而之前我们看到的threshold = (int)(capacity
* loadFactor);
如果在默认情况下,一个HashMap的容量为16,加载因子为0.75,那么阀值就是12,所以在往HashMap中put的值到达12时,它将自动扩
容两倍,如果两个线程同时遇到HashMap的大小达到12的倍数时,就很有可能会出现在将oldTable转移到newTable的过程中遇到问题,从
而导致最终的HashMap的值存储异常。
JDK1.0引入了第一个关联的集合类HashTable,它是线程安全的。 HashTable的所有方法都是同步的。
JDK2.0引入了HashMap,它提供了一个不同步的基类和一个同步的包装器synchronizedMap。synchronizedMap被称为
有条件的线程安全类。
JDK5.0util.concurrent包中引入对Map线程安全的实现ConcurrentHashMap,比起synchronizedMap,
它提供了更高的灵活性。同时进行的读和写操作都可以并发地执行。
所以在开始的测试中,如果我们采用ConcurrentHashMap,它的表现就很稳定,所以以后如果使用Map实现本地缓存,为了提高并发时的稳定
性,还是建议使用ConcurrentHashMap。
====================================================================
另外,还有一个我们经常使用的ArrayList也是非线程安全的,网上看到的有一个解释是这样:
一个 ArrayList 类,在添加一个元素的时候,它可能会有两步来完成:1. 在 Items[Size] 的位置存放此元素;2.
增大 Size 的值。
在单线程运行的情况下,如果 Size = 0,添加一个元素后,此元素在位置 0,而且 Size=1;
而如果是在多线程情况下,比如有两个线程,线程 A 先将元素存放在位置 0。但是此时 CPU 调度线程A暂停,线程 B
得到运行的机会。线程B也将元素放在位置0,(因为size还未增长),完了之后,两个线程都是size++,结果size变成2,而只有
items[0]有元素。
util.concurrent包也提供了一个线程安全的ArrayList替代者CopyOnWriteArrayList。
本文转载自:http://www.blogjava.net/lukangping/articles/331089.html
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 java.util.current 的文章

 

随机推荐