欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于Java HashMap的死循環(huán)的啟示詳解

 更新時(shí)間:2013年05月13日 11:43:23   作者:  
本篇文章是對(duì)Java HashMap的死循環(huán)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下

一、單線程改造為多線程也是個(gè)技術(shù)活

正如我們看到耗子叔叔博客里寫的那樣,原來(lái)是單線程的應(yīng)用程序,”后來(lái),我們的程序性能有問(wèn)題,所以需要變成多線程的,于是,變成多線程后到了線上,發(fā)現(xiàn)程序經(jīng)常占了100%的CPU“。

考慮到是淘寶的工程師曝出來(lái)的問(wèn)題,他們的技術(shù)基礎(chǔ)一般都很扎實(shí),連他們都用錯(cuò)了,所以把單線程改造為多線程并不是想象中的那么簡(jiǎn)單,我認(rèn)為。

你可能很不服氣地反問(wèn),淘寶的工程師又怎么了,單線程改為多線程有什么難的?無(wú)非就是應(yīng)用現(xiàn)有的多線程技術(shù)嘛,你看,我有非常強(qiáng)烈的線程安全意識(shí),我知道同步、死鎖、競(jìng)態(tài)條件,還知道lock free和線程安全容器,還知道各種線程安全同步構(gòu)造……難道還寫不出線程安全的應(yīng)用程序?

實(shí)際情況是,線程安全的應(yīng)用程序并不一定因?yàn)槟阌性鷮?shí)的線程安全基礎(chǔ)和開(kāi)發(fā)經(jīng)驗(yàn)就能夠?qū)懞玫摹?/P>

試著舉兩個(gè)例子:

1、使用線程安全容器通過(guò)索引取數(shù)據(jù)

很多人知道的線程安全容器,實(shí)際使用的時(shí)候并不一定不出現(xiàn)BUG,下面的(有隱患的)代碼就比較典型:

復(fù)制代碼 代碼如下:

        static int GetFirstOrDefault(ThreadSafeList<int> list)
        {
            if (list.Count > 0)
            {
                return list[0];
            }
            return 0;
        }

上面的函數(shù)參數(shù)list如果一開(kāi)始傳入一個(gè)元素總數(shù)為1的列表,大家能分析出上面的代碼會(huì)有什么問(wèn)題嗎?

關(guān)于線程安全容器,之前我恰好也總結(jié)過(guò)一篇文章<深入線程安全容器的實(shí)現(xiàn)方法>。線程安全容器并不真正安全,上面有問(wèn)題的代碼就是出自于這里。

 

2、多線程操作郵件的失誤

還有就是多線程應(yīng)用場(chǎng)景的分析可能不正確,曾經(jīng)因?yàn)橐粋€(gè)郵件收發(fā)程序的性能問(wèn)題,我也大膽改造過(guò)應(yīng)用程序,改來(lái)改去就出現(xiàn)了重大BUG,

大家可以看看我痛心疾首總結(jié)過(guò)的<基于一個(gè)應(yīng)用程序多線程誤用的分析詳解>。

 

上面舉的這兩個(gè)例子,我只是想說(shuō)明,多線程應(yīng)用程序中,因?yàn)榫€程安全產(chǎn)生的BUG其實(shí)是很微妙的,一個(gè)考慮不周或者認(rèn)識(shí)不夠深刻,出現(xiàn)問(wèn)題的可能性簡(jiǎn)直防不勝防。

二、ReHash的代價(jià)

上面第一點(diǎn)主要是閑談線程安全,接著我們也說(shuō)說(shuō)哈希表,深刻理解消耗成本很大的ReHash。

我們平常理解中的哈希表是“以空間換時(shí)間的一種數(shù)據(jù)結(jié)構(gòu)”。這樣說(shuō)的太久了,大家可能會(huì)有一種直觀上的錯(cuò)覺(jué),就是哈希表犧牲的是空間,爭(zhēng)取的是時(shí)間。

但是,ReHash的過(guò)程其實(shí)是空間和時(shí)間的雙重重大損失,因?yàn)榉治鲈创a,我們知道ReHash的過(guò)程其實(shí)就是一個(gè)動(dòng)態(tài)擴(kuò)容的過(guò)程,而哈希表的擴(kuò)容是個(gè)空間和時(shí)間消耗都非常驚人的內(nèi)部操作。

為什么說(shuō)ReHash是個(gè)空間和時(shí)間消耗都非常驚人的內(nèi)部操作呢?

1、原來(lái)當(dāng)我們對(duì)哈希結(jié)構(gòu)的容器進(jìn)行擴(kuò)容時(shí),散列表內(nèi)部要重新new一個(gè)更大的數(shù)組,然后把原來(lái)數(shù)組的內(nèi)容拷貝到新數(shù)組,并進(jìn)行重新散列;

2、new出來(lái)的這個(gè)更大的新數(shù)組容量有多大也是一門學(xué)問(wèn),一般來(lái)說(shuō),新數(shù)組的大小會(huì)設(shè)置成原數(shù)組雙倍大小的相近的一個(gè)素?cái)?shù)(.NET中這個(gè)素?cái)?shù)的生成還有一定的技巧)。

從1和2這兩點(diǎn)可以看出,ReHash的代價(jià)確實(shí)非常高。在不久以前我碰巧寫過(guò)一篇關(guān)于.NET容器的動(dòng)態(tài)擴(kuò)容的文章<解析從源碼分析常見(jiàn)的基于Array的數(shù)據(jù)結(jié)構(gòu)動(dòng)態(tài)擴(kuò)容機(jī)制的詳解>,其中也淺顯總結(jié)了.NET的HashTable的擴(kuò)容機(jī)制,現(xiàn)在對(duì)照J(rèn)ava中的HashMap源碼,看到熟悉的ReHash函數(shù)命名,再看一遍.NET中的實(shí)現(xiàn),果然有比較才能有提高。

至于我們平時(shí)所理解的“以空間換時(shí)間“,其實(shí)是指哈希具有O(1)復(fù)雜度的數(shù)據(jù)檢索效率,但它受填充因子影響,空間開(kāi)銷通常很大,空間利用率不高。

所以我們常常說(shuō)哈希表適用于讀操作頻繁,寫操作較少應(yīng)用場(chǎng)景,比如把哈希表當(dāng)做緩存容器,于我心有戚戚焉。

最后看到這句“有人把這個(gè)問(wèn)題報(bào)給了Sun,不過(guò)Sun不認(rèn)為這個(gè)是一個(gè)問(wèn)題。因?yàn)镠ashMap本來(lái)就不支持并發(fā)。要并發(fā)就用ConcurrentHashmap…”

根據(jù)實(shí)際開(kāi)發(fā)經(jīng)驗(yàn),線程安全的容器并不真正線程安全,會(huì)用ConcurrentHashmap也只是進(jìn)入初級(jí)階段,同時(shí)忍不住要感慨下當(dāng)年如日中天風(fēng)光無(wú)限的Sun。

相關(guān)文章

  • SpringCloud中的分布式鎖用法示例詳解(Java+Redis SETNX命令)

    SpringCloud中的分布式鎖用法示例詳解(Java+Redis SETNX命令)

    在Spring Cloud項(xiàng)目中,使用Java和Redis結(jié)合實(shí)現(xiàn)的分布式鎖可以確保訂單的一致性和并發(fā)控制,分布式鎖的使用能夠在多個(gè)實(shí)例同時(shí)提交訂單時(shí),僅有一個(gè)實(shí)例可以成功進(jìn)行操作,本文給大家介紹Spring,Cloud中的分布式鎖用法詳解(Java+Redis SETNX命令),感興趣的朋友一起看看吧
    2023-10-10
  • springboot后端如何實(shí)現(xiàn)攜帶token登陸

    springboot后端如何實(shí)現(xiàn)攜帶token登陸

    這篇文章主要介紹了springboot后端如何實(shí)現(xiàn)攜帶token登陸,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • java中方法遞歸的簡(jiǎn)單示例

    java中方法遞歸的簡(jiǎn)單示例

    這篇文章主要給大家介紹了關(guān)于java中方法遞歸的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Java中樹(shù)的存儲(chǔ)結(jié)構(gòu)實(shí)現(xiàn)示例代碼

    Java中樹(shù)的存儲(chǔ)結(jié)構(gòu)實(shí)現(xiàn)示例代碼

    本篇文章主要介紹了Java中樹(shù)的存儲(chǔ)結(jié)構(gòu)實(shí)現(xiàn)示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-09-09
  • java驗(yàn)證電話號(hào)碼的方法

    java驗(yàn)證電話號(hào)碼的方法

    這篇文章主要介紹了java驗(yàn)證電話號(hào)碼的方法,需要的朋友可以參考下
    2014-02-02
  • Java編譯器用maven打war包出錯(cuò)解決辦法

    Java編譯器用maven打war包出錯(cuò)解決辦法

    這篇文章主要介紹了用maven打war包出錯(cuò)的解決辦法,需要的朋友可以參考下
    2018-03-03
  • Spring?Security中使用authorizeRequests遇到的問(wèn)題小結(jié)

    Spring?Security中使用authorizeRequests遇到的問(wèn)題小結(jié)

    Spring?是非常流行和成功的?Java?應(yīng)用開(kāi)發(fā)框架,Spring?Security?正是?Spring?家族中的成員,這篇文章主要介紹了Spring?Security中使用authorizeRequests遇到的問(wèn)題,需要的朋友可以參考下
    2023-02-02
  • java報(bào)錯(cuò)Cause: java.sql.SQLException問(wèn)題解決

    java報(bào)錯(cuò)Cause: java.sql.SQLException問(wèn)題解決

    本文主要介紹了java報(bào)錯(cuò)Cause: java.sql.SQLException問(wèn)題解決,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-08-08
  • 三種Java打印PDF文檔的實(shí)例代碼

    三種Java打印PDF文檔的實(shí)例代碼

    這篇文章主要介紹了三種Java 打印PDF文檔的方法,文中代碼非常詳細(xì),供大家學(xué)習(xí)和參考,感興趣的朋友快來(lái)了解下
    2020-06-06
  • java使用IO流對(duì)數(shù)組排序?qū)嵗v解

    java使用IO流對(duì)數(shù)組排序?qū)嵗v解

    在本篇文章里小編給大家整理的是一篇關(guān)于java使用IO流對(duì)數(shù)組排序?qū)嵗v解內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。
    2021-02-02

最新評(píng)論