<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 12, comments - 8, trackbacks - 0, articles - 5
      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

    2010年11月18日

    博客做了遷移,新的地址:觀云的BLOG https://yeas.fun/
    新博課主要用于記錄一些系列的技術(shù)文章,今年的一個(gè)目標(biāo)就是深入研究JVM底層,我會(huì)把一些學(xué)習(xí)心得記錄下來(lái),也歡迎大家一起討論~

    posted @ 2020-04-18 10:12 楊羅羅 閱讀(218) | 評(píng)論 (0)編輯 收藏

    現(xiàn)在網(wǎng)絡(luò)那么發(fā)達(dá),我們上網(wǎng)的每個(gè)人勢(shì)必會(huì)在各個(gè)網(wǎng)站上登陸,那勢(shì)必會(huì)有一堆密碼需要管理,那怎么能記住那么多網(wǎng)站的密碼呢?我之前的做法是設(shè)置幾個(gè)常用的密碼,好多不重要的網(wǎng)站用一個(gè),重要的網(wǎng)站用一個(gè),然后...CSDN密碼泄露之后,只得吭哧吭哧的改一堆密碼。那種痛苦真的是呵呵呵

    那有沒(méi)有什么方式可以方便的管理密碼呢?

    那就是LastPass的工作,它是一款跨平臺(tái)密碼管理軟件。你在每個(gè)網(wǎng)站上都可以隨機(jī)生成一個(gè)密碼,然后軟件會(huì)自動(dòng)記住,你只需要記住這個(gè)軟件的主密碼就可以了。超方便!

    為什么要用LastPass?

    我用LastPass,是因?yàn)樗梢园惭b瀏覽器插件,之后你在網(wǎng)站的注冊(cè),它會(huì)自動(dòng)提醒你要不要加入它的密碼庫(kù),你在網(wǎng)站的登陸它會(huì)自動(dòng)幫你填寫(xiě)賬號(hào)密碼,甚至于一些常用的表單(比如說(shuō)身份證、公司地址、銀行卡等)你可以提前設(shè)置好,它也會(huì)自動(dòng)幫你填寫(xiě),我再也不用記那么多密碼了,一切都是自動(dòng)化。
    如果你經(jīng)常有國(guó)外的帳號(hào),比如說(shuō)google等大公司,LastPass甚至提供了一鍵改密碼的功能,好方便!

    支持智能手機(jī)么?

    當(dāng)然!現(xiàn)在智能機(jī)那么流行,不能在智能機(jī)上用,簡(jiǎn)直不能忍。當(dāng)你安裝了IOS軟件之后,在打開(kāi)網(wǎng)站登錄界面,點(diǎn)擊下方的向上小箭頭,選擇LassPass軟件,點(diǎn)擊Touch ID,好了,密碼自動(dòng)完成,世界頓時(shí)清凈了,想想以前在手機(jī)上輸入超長(zhǎng)的密碼,跪了!

    真的安全嗎?

    有的人擔(dān)心密碼泄露問(wèn)題,其實(shí)對(duì)于LastPass沒(méi)啥必要,因?yàn)長(zhǎng)astPass存儲(chǔ)的都是加密文件,只要你的主密碼不泄露,別人即使拿到你的網(wǎng)上的密碼,也是加密的,沒(méi)法用。

    它收費(fèi)嗎?

    好東西都要收費(fèi),價(jià)格也還可以,幾十塊一年,其實(shí)收費(fèi)版和免費(fèi)版對(duì)于普通用戶(hù),最重要的區(qū)別就是:免費(fèi)版帳號(hào)密碼不能云同步

    免費(fèi)獲得一個(gè)月的高級(jí)賬戶(hù)權(quán)限

    https://lastpass.com/f?18430702  通過(guò)這個(gè)地址注冊(cè),則會(huì)免費(fèi)獲得一個(gè)月高級(jí)賬戶(hù)權(quán)限

    最后也是最重要的:

    點(diǎn)擊這個(gè)鏈接,輸入剛剛你注冊(cè)的郵箱,則會(huì)送半年的高級(jí)賬戶(hù),記住一個(gè)密碼,就記住了所有密碼,就是那么簡(jiǎn)單!

    posted @ 2016-01-13 14:19 楊羅羅 閱讀(349) | 評(píng)論 (0)編輯 收藏

    一. 應(yīng)用場(chǎng)景

    在大型分布式應(yīng)用中,我們經(jīng)常碰到在多數(shù)據(jù)庫(kù)之間的數(shù)據(jù)同步問(wèn)題,比如說(shuō)一款游戲,在玩家注冊(cè)后,可以馬上登陸進(jìn)入服務(wù)器,數(shù)據(jù)在一個(gè)IDC更新,其它IDC立即可見(jiàn)。為了簡(jiǎn)化思路,我們這里稱(chēng)玩家注冊(cè)的數(shù)據(jù)庫(kù)(數(shù)據(jù)來(lái)源庫(kù))為中心庫(kù),同步目的地的數(shù)據(jù)庫(kù)為分站庫(kù)。

    在分布式領(lǐng)域有個(gè)CAP理論,是說(shuō)Consistency(一致性), Availability(可用性), Partition tolerance(分區(qū)和容錯(cuò)) 三部分在系統(tǒng)實(shí)現(xiàn)只可同時(shí)滿(mǎn)足二點(diǎn),無(wú)法三者兼顧。

    能做的

    · 數(shù)據(jù)快速搬運(yùn)到指定的IDC節(jié)點(diǎn)

    · 數(shù)據(jù)傳遞過(guò)程中失敗時(shí),重新傳遞

    · 監(jiān)控?cái)?shù)據(jù)傳遞流程

    · 故障轉(zhuǎn)移

    · 數(shù)據(jù)版本控制

    · 分配全局唯一的ID

    不能做的

    · 不參與業(yè)務(wù)行為,業(yè)務(wù)操作只能通過(guò)注冊(cè)的方式集成

    · 不保存業(yè)務(wù)數(shù)據(jù),不提供傳遞的業(yè)務(wù)的查詢(xún)

    二.系統(tǒng)要求

    1.數(shù)據(jù)快速同步:除去網(wǎng)絡(luò)原因,正常情況下從來(lái)源庫(kù)同步到接收庫(kù)的時(shí)間不超過(guò)300m2.高并發(fā):?jiǎn)蝹€(gè)應(yīng)用每秒同步2000條記錄
    3.可伸縮性,在資源達(dá)到上限時(shí)能通過(guò)增加應(yīng)用分散處理后期增長(zhǎng)的壓力
    4.數(shù)據(jù)完整性要求,在數(shù)據(jù)同步過(guò)程中保證數(shù)據(jù)不丟失和數(shù)據(jù)安全
    5.故障轉(zhuǎn)移和數(shù)據(jù)恢復(fù)功能

    三.設(shè)計(jì)思路

    系統(tǒng)優(yōu)化,最常用的就是進(jìn)行業(yè)務(wù)切割,將總?cè)蝿?wù)切割為許多子任務(wù),分區(qū)塊分析系統(tǒng)中可能存在的性能瓶頸并有針對(duì)性地進(jìn)行優(yōu)化,在本系統(tǒng)中,主要業(yè)務(wù)包含以下內(nèi)容:
    1.Syncer:外部接口,接收同步數(shù)據(jù)請(qǐng)求,初始化同步系統(tǒng)的一些必要數(shù)據(jù)
    2.Delivery:將同步數(shù)據(jù)按照業(yè)務(wù)或優(yōu)先級(jí)進(jìn)行分發(fā),并記錄分發(fā)結(jié)果
    3.Batch:分站庫(kù)收到同步數(shù)據(jù)后,根據(jù)不同的業(yè)務(wù)類(lèi)型調(diào)用相應(yīng)的業(yè)務(wù)邏輯處理數(shù)據(jù)
    基于以上三塊業(yè)務(wù)功能,我們可以把整個(gè)數(shù)據(jù)同步流程切割為3個(gè)應(yīng)用,具體如下圖顯示。在Syncer端應(yīng)用中,我們需要將原始同步數(shù)據(jù)和分發(fā)的分站進(jìn)行存儲(chǔ),以備失敗恢復(fù),此時(shí)如果采用數(shù)據(jù)庫(kù)進(jìn)行存儲(chǔ),勢(shì)必會(huì)受限于數(shù)據(jù)庫(kù)性能影響,因此我們采用了高效的key-value風(fēng)格存儲(chǔ)的redis服務(wù)來(lái)記錄數(shù)據(jù),同時(shí)在不同應(yīng)用之間采用隊(duì)列(Httpsqs服務(wù))的方式來(lái)進(jìn)行通訊,同時(shí)也保證的數(shù)據(jù)通訊的順序性,為之后的順序同步做好基礎(chǔ)。
    Httpsqs提供了http風(fēng)格的數(shù)據(jù)操作模式,業(yè)務(wù)編碼非常簡(jiǎn)單,同時(shí)也提供了web形式的隊(duì)列處理情況查詢(xún),這是選擇它做隊(duì)列服務(wù)很大一部分原因:方便業(yè)務(wù)操作和性能監(jiān)控。

    四.數(shù)據(jù)流轉(zhuǎn) 

    綠色-正常流程、紅色-異常流程

    隊(duì)列處理

    根據(jù)業(yè)務(wù)劃分隊(duì)列名稱(chēng),每個(gè)隊(duì)列再劃分為三個(gè)關(guān)聯(lián)隊(duì)列:正常隊(duì)列(Normal)、重試隊(duì)列(Retry)、死亡隊(duì)列(Death),處理流程為:

    【進(jìn)程A】把數(shù)據(jù)先放入正常隊(duì)列,如果放置失敗寫(xiě)恢復(fù)日志

    【進(jìn)程B】監(jiān)聽(tīng)正常隊(duì)列,獲取隊(duì)列數(shù)據(jù)并進(jìn)行業(yè)務(wù)處理,處理失敗放入重試隊(duì)列

    【進(jìn)程C】監(jiān)聽(tīng)重試隊(duì)列,過(guò)幾秒獲取隊(duì)列數(shù)據(jù)并重新進(jìn)行業(yè)務(wù)處理,處理失敗放入死亡隊(duì)列

    【進(jìn)程D】監(jiān)聽(tīng)死亡隊(duì)列,獲取隊(duì)列數(shù)據(jù)并重新進(jìn)行業(yè)務(wù)處理,處理失敗重新放入死亡隊(duì)列尾部,等待下一次輪回

    業(yè)務(wù)處理失敗如果無(wú)法再次放入隊(duì)列,記錄恢復(fù)日志

    數(shù)據(jù)同步流程

    1發(fā)送數(shù)據(jù),支持Http POST:curl -d "經(jīng)過(guò)URL編碼的文本消息",如"http://host:port/sync_all/register"
    或者Http GET:curl "http://host:port/sync_all/register?data=經(jīng)過(guò)URL編碼的文本消息"

    sync-syncer接收到同步數(shù)據(jù)請(qǐng)求,創(chuàng)建sid并分解出需要同步的節(jié)點(diǎn)個(gè)數(shù),把原始數(shù)據(jù)和子任務(wù)寫(xiě)入redis中,sid寫(xiě)入httpsqs中

    sync-delivery監(jiān)聽(tīng)中心httpsqs隊(duì)列,根據(jù)sid從redis獲取到原始數(shù)據(jù)和需要同步的節(jié)點(diǎn)地址,往其他節(jié)點(diǎn)發(fā)送數(shù)據(jù),流程如按"隊(duì)列處理流程"進(jìn)行

    sync-batch監(jiān)聽(tīng)分節(jié)點(diǎn)的httpsqs隊(duì)列,調(diào)用已經(jīng)注冊(cè)的處理器處理隊(duì)列數(shù)據(jù),流程如按"隊(duì)列處理流程"進(jìn)行

    三. 恢復(fù)和監(jiān)控

    恢復(fù)數(shù)據(jù)源

    · httpsqs中的死亡隊(duì)列 - 業(yè)務(wù)處理暫時(shí)處理不了的數(shù)據(jù)

    · recovery日志文件 - 其它異常情況下的數(shù)據(jù),例如網(wǎng)絡(luò)無(wú)法連接、內(nèi)部服務(wù)不可用

    數(shù)據(jù)恢復(fù)

    獨(dú)立的應(yīng)用來(lái)處理正常流程中沒(méi)有完成的任務(wù),主要功能有:

    · 監(jiān)聽(tīng)死亡隊(duì)列,進(jìn)行業(yè)務(wù)重做,再次執(zhí)行失敗時(shí)將執(zhí)行次數(shù)+1,最大執(zhí)行次數(shù)為5(默認(rèn)),超出上限則記錄到恢復(fù)日志中

    · 讀取恢復(fù)日志,重新放入死亡隊(duì)列

    應(yīng)用監(jiān)控

    · 使用scribe日志框架服務(wù)業(yè)務(wù)日志的采集和監(jiān)控

    · 收集重要的業(yè)務(wù)操作日志

    · 動(dòng)態(tài)的開(kāi)啟/關(guān)閉某類(lèi)業(yè)務(wù)日志

    · 對(duì)redis進(jìn)行監(jiān)控

    · 對(duì)httpsps,監(jiān)控隊(duì)列個(gè)數(shù),每個(gè)隊(duì)列的狀態(tài)

    四. 數(shù)據(jù)結(jié)構(gòu)

    {"sid":111,"type":"reg","v":1,"data":"hello world","ctime":65711321800,"exec":1}

    · sid(sync id) - 全局唯一id

    · v(version) - 版本號(hào)

    · data - 業(yè)務(wù)數(shù)據(jù)

    · ctime(create time) - 創(chuàng)建時(shí)間(毫秒)

    · exec - 可選,執(zhí)行次數(shù)

    類(lèi)別

    key格式

    value格式

    備注

    redis原始數(shù)據(jù)

    sync:<業(yè)務(wù)類(lèi)型>:<sid>

    {"ctime":65711321800,"v":1,"data":"hello world"}

    分站沒(méi)有此項(xiàng)

    redis業(yè)務(wù)附加任務(wù)

    sync:<業(yè)務(wù)類(lèi)型>:<sid>:sub

    set類(lèi)型,保存需要同步的節(jié)點(diǎn)id,例如[1,3,5]

    分發(fā)確認(rèn)Set數(shù)據(jù)結(jié)構(gòu) 

    httpsqs隊(duì)列

    sync:<業(yè)務(wù)類(lèi)型> 
    sync:<業(yè)務(wù)類(lèi)型>:retry 
    sync:<業(yè)務(wù)類(lèi)型>:death

    {"sid":111,"type":"pp_register","exec":1} 

    中心隊(duì)列內(nèi)容,key中<業(yè)務(wù)類(lèi)型>是可選項(xiàng) 

    httpsqs隊(duì)列

    sync:<業(yè)務(wù)類(lèi)型> 
    sync:<業(yè)務(wù)類(lèi)型>:retry 
    sync:<業(yè)務(wù)類(lèi)型>:death

    {"sid":111,"v":1,"data":"hello world","ctime":65711321800,"exec":1} 

    分站隊(duì)列內(nèi)容,包含業(yè)務(wù)數(shù)據(jù) 

    所有的key都小寫(xiě),以 ':' 作為分隔符

    五.編碼及測(cè)試結(jié)果

    經(jīng)過(guò)編碼和測(cè)試,在內(nèi)網(wǎng)環(huán)境下,在無(wú)數(shù)據(jù)庫(kù)限制的情況下,單應(yīng)用可以傳遞1500條/秒,基本滿(mǎn)足業(yè)務(wù)需求。如果需進(jìn)一步擴(kuò)展,采用集群式布署可使得吞吐量成倍的增長(zhǎng)。

    posted @ 2011-04-06 15:50 楊羅羅 閱讀(3634) | 評(píng)論 (3)編輯 收藏

         摘要: java.util.concurrent 包含許多線(xiàn)程安全、測(cè)試良好、高性能的并發(fā)構(gòu)建塊。不客氣地說(shuō),創(chuàng)建 java.util.concurrent 的目的就是要實(shí)現(xiàn) Collection 框架對(duì)數(shù)據(jù)結(jié)構(gòu)所執(zhí)行的并發(fā)操作。通過(guò)提供一組可靠的、高性能并發(fā)構(gòu)建塊,開(kāi)發(fā)人員可以提高并發(fā)類(lèi)的線(xiàn)程安全、可伸縮性、性能、可讀性和可靠性。 如果一些類(lèi)名看起來(lái)相似,可能是因?yàn)?java.util.concurr...  閱讀全文

    posted @ 2010-12-08 17:40 楊羅羅 閱讀(818) | 評(píng)論 (0)編輯 收藏

    AQS中有一個(gè)state字段(int類(lèi)型,32位)用來(lái)描述有多少線(xiàn)程獲持有鎖。在獨(dú)占鎖的時(shí)代這個(gè)值通常是0或者1(如果是重入的就是重入的次數(shù)),在共享鎖的時(shí)代就是持有鎖的數(shù)量。
    自旋等待適合于比較短的等待,而掛起線(xiàn)程比較適合那些比較耗時(shí)的等待。

    鎖競(jìng)爭(zhēng)

    影響鎖競(jìng)爭(zhēng)性的條件有兩個(gè):鎖被請(qǐng)求的頻率和每次持有鎖的時(shí)間。顯然當(dāng)而這二者都很小的時(shí)候,鎖競(jìng)爭(zhēng)不會(huì)成為主要的瓶頸。但是如果鎖使用不當(dāng),導(dǎo)致二者都比較大,那么很有可能CPU不能有效的處理任務(wù),任務(wù)被大量堆積。

    所以減少鎖競(jìng)爭(zhēng)的方式有下面三種:

    1. 減少鎖持有的時(shí)間
    2. 減少鎖請(qǐng)求的頻率
    3. 采用共享鎖取代獨(dú)占鎖

    死鎖

    1.一種情況是線(xiàn)程A永遠(yuǎn)不釋放鎖,結(jié)果B一直拿不到鎖,所以線(xiàn)程B就“死掉”了
    2.第二種情況下,線(xiàn)程A擁有線(xiàn)程B需要的鎖Y,同時(shí)線(xiàn)程B擁有線(xiàn)程A需要的鎖X,那么這時(shí)候線(xiàn)程A/B互相依賴(lài)對(duì)方釋放鎖,于是二者都“死掉”了。
    3.如果一個(gè)線(xiàn)程總是不能被調(diào)度,那么等待此線(xiàn)程結(jié)果的線(xiàn)程可能就死鎖了。這種情況叫做線(xiàn)程饑餓死鎖。比如說(shuō)非公平鎖中,如果某些線(xiàn)程非常活躍,在高并發(fā)情況下這類(lèi)線(xiàn)程可能總是拿到鎖,那么那些活躍度低的線(xiàn)程可能就一直拿不到鎖,這樣就發(fā)生了“饑餓死”。

    避免死鎖的解決方案是:
    1.盡可能的按照鎖的使用規(guī)范請(qǐng)求鎖,另外鎖的請(qǐng)求粒度要小(不要在不需要鎖的地方占用鎖,鎖不用了盡快釋放);
    2.在高級(jí)鎖里面總是使用tryLock或者定時(shí)機(jī)制(就是指定獲取鎖超時(shí)的時(shí)間,如果時(shí)間到了還沒(méi)有獲取到鎖那么就放棄)。高級(jí)鎖(Lock)里面的這兩種方式可以有效的避免死鎖。

    posted @ 2010-12-03 10:11 楊羅羅 閱讀(1841) | 評(píng)論 (0)編輯 收藏

         摘要: 內(nèi)部類(lèi)詳解  1、定義    一個(gè)類(lèi)的定義放在另一個(gè)類(lèi)的內(nèi)部,這個(gè)類(lèi)就叫做內(nèi)部類(lèi)。  Java代碼  public class First {   public class Contents{   &nb...  閱讀全文

    posted @ 2010-11-25 16:27 楊羅羅 閱讀(5034) | 評(píng)論 (1)編輯 收藏

    Spring中提供一些Aware相關(guān)接口,像是BeanFactoryAware、 ApplicationContextAware、ResourceLoaderAware、ServletContextAware等等,實(shí)現(xiàn)這些 Aware接口的Bean在被初始之后,可以取得一些相對(duì)應(yīng)的資源,例如實(shí)現(xiàn)BeanFactoryAware的Bean在初始后,Spring容器將會(huì)注入BeanFactory的實(shí)例,而實(shí)現(xiàn)ApplicationContextAware的Bean,在Bean被初始后,將會(huì)被注入 ApplicationContext的實(shí)例等等。

     Bean取得BeanFactory、ApplicationContextAware的實(shí)例目的是什么,一般的目的就是要取得一些檔案資源的存取、相 關(guān)訊息資源或是那些被注入的實(shí)例所提供的機(jī)制,例如ApplicationContextAware提供了publishEvent()方法,可以支持基于Observer模式的事件傳播機(jī)制。

     ApplicationContextAware接口的定義如下:

    ApplicationContextAware.java

    public interface ApplicationContextAware {

        void setApplicationContext(ApplicationContext context);

    }


     我們這邊示范如何透過(guò)實(shí)現(xiàn)ApplicationContextAware注入ApplicationContext來(lái)實(shí)現(xiàn)事件傳播,首先我們的HelloBean如下:

    HelloBean.java

    package onlyfun.caterpillar;

     

    import org.springframework.context.*;

     

    public class HelloBean implements ApplicationContextAware {

        private ApplicationContext applicationContext;

        private String helloWord = "Hello!World!";

      

        public void setApplicationContext(ApplicationContext context) {

            this.applicationContext = context;

        }

      

        public void setHelloWord(String helloWord) {

            this.helloWord = helloWord;

        }

      

        public String getHelloWord() {

            applicationContext.publishEvent(

                   new PropertyGettedEvent("[" + helloWord + "] is getted"));

            return helloWord;

        }

    }


     ApplicationContext會(huì)由Spring容器注入,publishEvent()方法需要一個(gè)繼承ApplicationEvent的對(duì)象,我們的PropertyGettedEvent繼承了ApplicationEvent,如下:

    PropertyGettedEvent.java

    package onlyfun.caterpillar;

     

    import org.springframework.context.*;

     

    public class PropertyGettedEvent extends ApplicationEvent {

        public PropertyGettedEvent(Object source) {

            super(source);

        }

    }


     當(dāng)ApplicationContext執(zhí)行publishEvent()后,會(huì)自動(dòng)尋找實(shí)現(xiàn)ApplicationListener接口的對(duì)象并通知其發(fā)生對(duì)應(yīng)事件,我們實(shí)現(xiàn)了PropertyGettedListener如下:

    PrppertyGettedListener.java

    package onlyfun.caterpillar;

     

    import org.springframework.context.*;

     

    public class PropertyGettedListener implements ApplicationListener {

        public void onApplicationEvent(ApplicationEvent event) {

            System.out.println(event.getSource().toString());  

        }

    }


     Listener必須被實(shí)例化,這我們可以在Bean定義檔中加以定義:

    <?xml version="1.0" encoding="UTF-8"?>

    <!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" "http://www.springframework.org/dtd/spring-beans.dtd">

    <beans>

        <bean id="propertyGetterListener" class="onlyfun.caterpillar.PropertyGettedListener"/>

     

        <bean id="helloBean" class="onlyfun.caterpillar.HelloBean">

            <property name="helloWord"><value>Hello!Justin!</value></property>

        </bean>

    </beans>


     我們寫(xiě)一個(gè)測(cè)試程序來(lái)測(cè)測(cè)事件傳播的運(yùn)行:

    Test.java

    package onlyfun.caterpillar;

     

    import org.springframework.context.*;

    import org.springframework.context.support.*;

     

    public class Test {

        public static void main(String[] args) {

            ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");

          

            HelloBean hello = (HelloBean) context.getBean("helloBean");

            System.out.println(hello.getHelloWord());

        }

    }


     執(zhí)行結(jié)果會(huì)如下所示:

    log4j:WARN No appenders could be found for logger

    (org.springframework.beans.factory.xml.XmlBeanDefinitionReader).

    log4j:WARN Please initialize the log4j system properly.

    org.springframework.context.support.ClassPathXmlApplicationContext:

    displayName=[org.springframework.context.support.ClassPathXmlApplicationContext;

    hashCode=33219526]; startup date=[Fri Oct 29 10:56:35 CST 2004];

    root of ApplicationContext hierarchy

    [Hello!Justin!] is getted

    Hello!Justin!


     以上是以實(shí)現(xiàn)事件傳播來(lái)看看實(shí)現(xiàn)Aware接口取得對(duì)應(yīng)對(duì)象后,可以進(jìn)行的動(dòng)作,同樣的,您也可以實(shí)現(xiàn)ResourceLoaderAware接口:

    ResourceLoaderAware.java

    public interface ResourceLoaderAware {

        void setResourceLoader(ResourceLoader loader);

    }


     實(shí)現(xiàn)ResourceLoader的Bean就可以取得ResourceLoader的實(shí)例,如此就可以使用它的getResource()方法,這對(duì)于必須存取檔案資源的Bean相當(dāng)有用。

     基本上,Spring雖然提供了這些Aware相關(guān)接口,然而B(niǎo)ean上若實(shí)現(xiàn)了這些界面,就算是與Spring發(fā)生了依賴(lài),從另一個(gè)角度來(lái)看,雖然您可以直接在Bean上實(shí)現(xiàn)這些接口,但您也可以透過(guò)setter來(lái)完成依賴(lài)注入,例如:

    HelloBean.java

    package onlyfun.caterpillar;

     

    import org.springframework.context.*;

     

    public class HelloBean {

        private ApplicationContext applicationContext;

        private String helloWord = "Hello!World!";

      

        public void setApplicationContext(ApplicationContext context) {

            this.applicationContext = context;

        }

      

        public void setHelloWord(String helloWord) {

            this.helloWord = helloWord;

        }

      

        public String getHelloWord() {

            applicationContext.publishEvent(new PropertyGettedEvent("[" + helloWord + "] is getted"));

            return helloWord;

        }

    }


     注意這次我們并沒(méi)有實(shí)現(xiàn)ApplicationContextAware,我們?cè)诔绦蛑锌梢宰孕凶⑷階pplicationContext實(shí)例:

    ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");

          

    HelloBean hello = (HelloBean) context.getBean("helloBean");

    hello.setApplicationContext(context);

    System.out.println(hello.getHelloWord());


     就Bean而言,降低了對(duì)Spring的依賴(lài),可以比較容易從現(xiàn)有的框架中脫離。

     

    posted @ 2010-11-24 11:14 楊羅羅 閱讀(7661) | 評(píng)論 (1)編輯 收藏

    在JDK 5之前Java語(yǔ)言是靠synchronized關(guān)鍵字保證同步的,這會(huì)導(dǎo)致有鎖(后面的章節(jié)還會(huì)談到鎖)。

    鎖機(jī)制存在以下問(wèn)題:

    (1)在多線(xiàn)程競(jìng)爭(zhēng)下,加鎖、釋放鎖會(huì)導(dǎo)致比較多的上下文切換和調(diào)度延時(shí),引起性能問(wèn)題。

    (2)一個(gè)線(xiàn)程持有鎖會(huì)導(dǎo)致其它所有需要此鎖的線(xiàn)程掛起。

    (3)如果一個(gè)優(yōu)先級(jí)高的線(xiàn)程等待一個(gè)優(yōu)先級(jí)低的線(xiàn)程釋放鎖會(huì)導(dǎo)致優(yōu)先級(jí)倒置,引起性能風(fēng)險(xiǎn)。

    volatile是不錯(cuò)的機(jī)制,但是volatile不能保證原子性。因此對(duì)于同步最終還是要回到鎖機(jī)制上來(lái)。

    獨(dú)占鎖是一種悲觀鎖,synchronized就是一種獨(dú)占鎖,會(huì)導(dǎo)致其它所有需要鎖的線(xiàn)程掛起,等待持有鎖的線(xiàn)程釋放鎖。而另一個(gè)更加有效的鎖就是樂(lè)觀鎖。所謂樂(lè)觀鎖就是,每次不加鎖而是假設(shè)沒(méi)有沖突而去完成某項(xiàng)操作,如果因?yàn)闆_突失敗就重試,直到成功為止。

    CAS 操作

    上面的樂(lè)觀鎖用到的機(jī)制就是CAS,Compare and Swap。

    CAS有3個(gè)操作數(shù),內(nèi)存值V,舊的預(yù)期值A(chǔ),要修改的新值B。當(dāng)且僅當(dāng)預(yù)期值A(chǔ)和內(nèi)存值V相同時(shí),將內(nèi)存值V修改為B,否則什么都不做。

    非阻塞算法 (nonblocking algorithms)

    一個(gè)線(xiàn)程的失敗或者掛起不應(yīng)該影響其他線(xiàn)程的失敗或掛起的算法。

    現(xiàn)代的CPU提供了特殊的指令,可以自動(dòng)更新共享數(shù)據(jù),而且能夠檢測(cè)到其他線(xiàn)程的干擾,而 compareAndSet() 就用這些代替了鎖定。

    拿出AtomicInteger來(lái)研究在沒(méi)有鎖的情況下是如何做到數(shù)據(jù)正確性的。

    private volatile int value;

    首先毫無(wú)以為,在沒(méi)有鎖的機(jī)制下可能需要借助volatile原語(yǔ),保證線(xiàn)程間的數(shù)據(jù)是可見(jiàn)的(共享的)。這樣才獲取變量的值的時(shí)候才能直接讀取。

    public final int get() {
            return value;
        }

    然后來(lái)看看++i是怎么做到的。

    public final int incrementAndGet() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                return next;
        }
    }

    在這里采用了CAS操作,每次從內(nèi)存中讀取數(shù)據(jù)然后將此數(shù)據(jù)和+1后的結(jié)果進(jìn)行CAS操作,如果成功就返回結(jié)果,否則重試直到成功為止。

    而compareAndSet利用JNI來(lái)完成CPU指令的操作。

    public final boolean compareAndSet(int expect, int update) {   
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
        }

    整體的過(guò)程就是這樣子的,利用CPU的CAS指令,同時(shí)借助JNI來(lái)完成Java的非阻塞算法。其它原子操作都是利用類(lèi)似的特性完成的。

    而整個(gè)J.U.C都是建立在CAS之上的,因此對(duì)于synchronized阻塞算法,J.U.C在性能上有了很大的提升。

    CAS看起來(lái)很爽,但是會(huì)導(dǎo)致“ABA問(wèn)題”。

    CAS算法實(shí)現(xiàn)一個(gè)重要前提需要取出內(nèi)存中某時(shí)刻的數(shù)據(jù),而在下時(shí)刻比較并替換,那么在這個(gè)時(shí)間差類(lèi)會(huì)導(dǎo)致數(shù)據(jù)的變化

    比如說(shuō)一個(gè)線(xiàn)程one從內(nèi)存位置V中取出A,這時(shí)候另一個(gè)線(xiàn)程two也從內(nèi)存中取出A,并且two進(jìn)行了一些操作變成了B,然后two又將V位置的數(shù)據(jù)變成A,這時(shí)候線(xiàn)程one進(jìn)行CAS操作發(fā)現(xiàn)內(nèi)存中仍然是A,然后one操作成功。盡管線(xiàn)程one的CAS操作成功,但是不代表這個(gè)過(guò)程就是沒(méi)有問(wèn)題的。如果鏈表的頭在變化了兩次后恢復(fù)了原值,但是不代表鏈表就沒(méi)有變化。因此前面提到的原子操作AtomicStampedReference/AtomicMarkableReference就很有用了。這允許一對(duì)變化的元素進(jìn)行原子操作。

    posted @ 2010-11-18 15:16 楊羅羅 閱讀(3125) | 評(píng)論 (1)編輯 收藏

    volatile保證線(xiàn)程間的數(shù)據(jù)是可見(jiàn)的(共享的),但不保證數(shù)據(jù)同步

    volatile相當(dāng)于synchronized的弱實(shí)現(xiàn),也就是說(shuō)volatile實(shí)現(xiàn)了類(lèi)似synchronized的語(yǔ)義,卻又沒(méi)有鎖機(jī)制。它確保對(duì)volatile字段的更新以可預(yù)見(jiàn)的方式告知其他的線(xiàn)程。
    volatile包含以下語(yǔ)義:
    (1)Java 存儲(chǔ)模型不會(huì)對(duì)valatile指令的操作進(jìn)行重排序:這個(gè)保證對(duì)volatile變量的操作時(shí)按照指令的出現(xiàn)順序執(zhí)行的。
    (2)volatile變量不會(huì)被緩存在寄存器中(只有擁有線(xiàn)程可見(jiàn))或者其他對(duì)CPU不可見(jiàn)的地方,每次總是從主存中讀取volatile變量的結(jié)果。也就是說(shuō)對(duì)于volatile變量的修改,其它線(xiàn)程總是可見(jiàn)的,并且不是使用自己線(xiàn)程棧內(nèi)部的變量。也就是在happens-before法則中,對(duì)一個(gè)valatile變量的寫(xiě)操作后,其后的任何讀操作理解可見(jiàn)此寫(xiě)操作的結(jié)果。

    volatile變量的特性不錯(cuò),但是volatile并不能保證線(xiàn)程安全的,也就是說(shuō)volatile字段的操作不是原子性的,volatile變量只能保證可見(jiàn)性(一個(gè)線(xiàn)程修改后其它線(xiàn)程能夠理解看到此變化后的結(jié)果),要想保證原子性,目前為止只能加鎖!

    volatile通常在下面的場(chǎng)景:

    volatile boolean done = false;



        
    while( ! done ){
            dosomething();
        }

     應(yīng)用volatile變量的三個(gè)原則:

    (1)寫(xiě)入變量不依賴(lài)此變量的值,或者只有一個(gè)線(xiàn)程修改此變量

    (2)變量的狀態(tài)不需要與其它變量共同參與不變約束

    (3)訪問(wèn)變量不需要加鎖

    posted @ 2010-11-18 14:45 楊羅羅 閱讀(1710) | 評(píng)論 (0)編輯 收藏

         摘要: JMM規(guī)范:  The rules for happens-before are:  Program order rule. Each action in a thread happens-before every action in that thread that comes later in the program order.  ...  閱讀全文

    posted @ 2010-11-18 14:42 楊羅羅 閱讀(1089) | 評(píng)論 (0)編輯 收藏

    主站蜘蛛池模板: 亚洲AV成人精品网站在线播放| 国产va免费精品观看精品| 亚洲成人在线网站| 成年人免费视频观看| 久久免费香蕉视频| 亚洲不卡视频在线观看| 国产精品亚洲综合一区| 久久久久久精品成人免费图片| 亚洲日韩中文字幕在线播放| 免费成人激情视频| 亚洲黄片手机免费观看| 亚洲一区二区三区高清不卡| 国产AV无码专区亚洲AWWW| 三级黄色片免费看| 九九美女网站免费| 亚洲va中文字幕| 日韩精品成人亚洲专区| 一级免费黄色毛片| 亚洲不卡中文字幕| 亚洲国产精品无码专区在线观看 | 免免费国产AAAAA片| 中国毛片免费观看| 羞羞网站免费观看| 色老板亚洲视频免在线观| 亚洲成在人线av| 精品亚洲视频在线观看| 精品免费国产一区二区三区| 69av免费观看| 免费观看成人久久网免费观看| 免费一级毛片在线播放视频免费观看永久 | 亚洲丁香婷婷综合久久| 亚洲福利一区二区三区| 亚洲国产精品SSS在线观看AV| 四虎影视永久免费观看| 女人18毛片水最多免费观看| 亚洲大片免费观看| 香蕉免费一区二区三区| 国产永久免费高清在线| 99精品免费视品| 91在线免费视频| 好男人资源在线WWW免费|