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

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

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

    Evan's Blog

    Java, software development and others.

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      28 隨筆 :: 0 文章 :: 73 評論 :: 0 Trackbacks

    2006年3月6日 #

    最近一個(gè)項(xiàng)目需要考慮多語言的用戶,自然就想采用utf-8編碼,所有JSP頁面都修改完畢,一切運(yùn)行正常,由于一直使用FF來檢測瀏覽器兼容性,今天不知怎的決定用IE來跑一下,發(fā)現(xiàn)所有表單提交的頁面都提示JS錯(cuò)誤,查了一下,發(fā)現(xiàn)是一個(gè)驗(yàn)證身份證的方法中有一個(gè)數(shù)組的初始化中保存了各個(gè)省市的名字,類似于:var area=['上海','北京']之類的形式。一般情況下,JS錯(cuò)誤我都是在FF中用FireBug調(diào)試的,可偏偏在FF中一切正常,這下就傻眼了,注釋掉這個(gè)語句自然沒問題,可怎么也想不出這么正常的一個(gè)賦值怎么會(huì)弄出個(gè)瀏覽器兼容的問題出來。折騰了一個(gè)下午,突然想到,是不是編碼的問題啊,將這個(gè)JS用utf-8編碼另存,一切ok。

    另外,采用utf-8編碼之后,用WinMerge比較文件時(shí),就會(huì)出來Information lost to encoding errors:之類的提示,心想,這個(gè)指定個(gè)編碼就可以了吧。在編輯=>選項(xiàng)中,果然看到代碼頁的指定,如是選擇指定代碼頁,輸入utf-8,點(diǎn)擊確定,被提示請輸入一個(gè)整數(shù),估計(jì)這時(shí)候大多數(shù)人和我一樣傻眼,utf-8的代碼頁是多少?好在有Google,調(diào)整不同的關(guān)鍵字,終于找到清炒苦瓜的一篇文章中提到utf-8的代碼頁是65001,并且也是為了解決WinMerge的亂碼問題,可是改完之后,并沒有起作用,這次沒有去懷疑這個(gè)代碼頁是不是正確,再仔細(xì)看一下那篇文章,嗯,人家明明說用的是2.6.8嘛,檢查一下自己的版本,2.6.0,是不是版本問題呢?來到WinMerge的網(wǎng)站,發(fā)現(xiàn)竟然已經(jīng)是2.6.12了,于是下載最新版本,然后將代碼頁改成65001,嗯,這下所有的中文注釋都乖乖出來了。
    posted @ 2008-01-05 21:41 Evan 閱讀(2833) | 評論 (1)編輯 收藏

         摘要: Apache反向代理設(shè)置  閱讀全文
    posted @ 2008-01-04 21:13 Evan 閱讀(5963) | 評論 (2)編輯 收藏

         摘要: 這個(gè)Blog,就象我久未清理的書桌,已經(jīng)落了厚厚的一層灰塵,在這個(gè)新年的第一天,決定用這樣一個(gè)夠噱頭的標(biāo)題,以一篇夠水的日志,來告訴自己,已經(jīng)是2008年了......  閱讀全文
    posted @ 2008-01-01 13:22 Evan 閱讀(319) | 評論 (0)編輯 收藏

         摘要: 不要假裝我們是一個(gè)文明古國了,傳統(tǒng)早已割裂,我們是個(gè)無根的民族,精神一片荒蕪,偽造出的傳統(tǒng)只加劇了我們的虛偽,凸顯了我們的空洞與脆弱。  閱讀全文
    posted @ 2007-08-31 21:28 Evan 閱讀(222) | 評論 (0)編輯 收藏

         摘要: 你是不是從svn 1.2甚至更早的版本就開始用Subversion了?是不是在用svnserve做服務(wù)器?是不是很認(rèn)真的讀了svn自帶的文檔?那么,很有可能,你也象我一樣,被它小小的忽悠了一把:)。  閱讀全文
    posted @ 2007-04-01 14:33 Evan 閱讀(3275) | 評論 (1)編輯 收藏

         摘要: 在網(wǎng)上兜到一篇文章,從講述一個(gè)譯者和一家出版社之間的糾紛,引申出了一些待人處世的道理,主要是關(guān)于一個(gè)人碰到不公平的事情的時(shí)候,應(yīng)該怎樣辦,覺得頗有道理。什么樣的人才是有力量的人呢,也許是那些能合理處理不合理的事情,甚至能讓不合理的事情最終轉(zhuǎn)化為多贏局面的人吧。人生要真能達(dá)到這樣一種境界,該是怎樣一副海闊憑魚躍(管它波濤洶涌還是風(fēng)平浪凈),天高任鳥飛(管它烏云閉日還是陽光普照)的從容畫面。  閱讀全文
    posted @ 2006-12-30 19:48 Evan 閱讀(1074) | 評論 (1)編輯 收藏

    好久沒有更新Blog了,看到還有人在關(guān)注這個(gè)Blog,很是慚愧。發(fā)現(xiàn)還是有人在使用Polarion的SVN Web Client,并且碰到了一些小問題,盡管我工作中幾乎不用這個(gè)客戶端,但當(dāng)初安裝的版本依然還在,所以決定稍微研究一下,但愿能給喜好這款軟件的人一些幫助。

    1. 為什么老是提示“Your credentials are not correct. Please check them and try again. ”?
    這個(gè)多半是svn初學(xué)者常碰到的問題,尤其在使用HTTP協(xié)議的時(shí)候。一開始大家都用svnserve來做svn的服務(wù)器,自然配置的是conf中的passwd。但如果采用HTTP協(xié)議的話,就得使用Basci HTTP Authentication了,需要用Apache提供的htpasswd來管理用戶和口令。這個(gè)的配置在svn自帶的幫助文件中第6章“httpd, the Apache HTTP Server”一節(jié)中有比較詳細(xì)的解釋。但如果你沒有通篇看完,在Apache中沒有加上Require valid-user指令的話,那是允許匿名操作的。我想,你不愿意留下這樣的安全漏洞吧。

    2. 怎樣配置多個(gè)repository
    這個(gè)也是實(shí)際中需要的,當(dāng)然,在它的readme中其實(shí)是說得很清楚的。但我們有些同志就是喜歡拿來就試,尤其是在有些類似于我這種其實(shí)語焉不詳?shù)奈恼聲r(shí),更是就喜歡照葫蘆畫瓢,而不去看最權(quán)威最原始的英文文檔了。要配置多個(gè)repository,以HTTP協(xié)議為例,在web.xml中要?jiǎng)h掉RepositoryUrl、Username、Password這3個(gè)參數(shù)的設(shè)置,然后加上ParentRepositoryDirectory參數(shù),值自然是指向svn倉庫的父目錄了,比如http://localhost/svn/,這個(gè)東西又是哪里來的呢?自然需要在Apache中配置,用SVNParentPath來指定svn倉庫的父目錄,Apache會(huì)自動(dòng)解析其下所有的倉庫的。這里要注意一下AuthzSVNAccessFile授權(quán)文件的寫法,這里將配置所有倉庫的存取權(quán)限,對于每個(gè)倉庫,需要用[倉庫名:/module]的方式來配置。

    3. 怎樣使用svn協(xié)議
    前面我一直用http協(xié)議做例子,實(shí)在是因?yàn)槲以谄?.5.0下沒有配置出來過svn協(xié)議:(。這次去其網(wǎng)站下載了個(gè)最新的nightly版本,發(fā)現(xiàn)其已經(jīng)能夠支持http, svn, svn+ssh, ssl和proxy等6種協(xié)議了。看看其代碼結(jié)構(gòu),好象也發(fā)生了很大的變化,估計(jì)應(yīng)該有比較大的改進(jìn)。于是,用這個(gè)版本試了一把,呵呵,輕而易舉就把svn協(xié)議給連通了,包括多倉庫的情況。并且其還改進(jìn)了原來設(shè)置父目錄地址時(shí)一定要在最后添加/的要求,估計(jì)原來在這個(gè)地方卡殼的朋友也不少吧:)。不過,新版本還是不支持中文文件名,看我以前的帖子自己改吧。

    Important: 由于svn webclient采用的javasvn(現(xiàn)已更名為svnkit)版本較低,用svn協(xié)議在提交老的文件時(shí)會(huì)失敗,但添加新的文件時(shí)沒有問題,所以,大家就不要再嘗試svn協(xié)議了。如果不采用SVN協(xié)議,則其官方發(fā)布的版本就沒什么問題了,已經(jīng)有網(wǎng)友重新打包了一個(gè)解決了中文文件名的版本,到這里下載。(Updated: 2007.1.20)
    posted @ 2006-12-27 13:04 Evan 閱讀(3635) | 評論 (2)編輯 收藏

         摘要: 使用Jarkata FileUpload最新版本解決SVNWebClient提交中文文件名或注釋時(shí)出錯(cuò)的問題。  閱讀全文
    posted @ 2006-05-14 20:11 Evan 閱讀(4836) | 評論 (11)編輯 收藏

         摘要: 在我的“[推薦]兩款好用的SVN Web Client”一文中曾經(jīng)提及我所看好的sventon中文支持不好的問題,于是在其論壇中提了個(gè)問題,今天收到他們的郵件,稱在其最新的代碼中已經(jīng)解決了中文的問題,今天下載更新后,發(fā)現(xiàn)的確解決了這個(gè)問題,呵呵,更新速度挺快的。  閱讀全文
    posted @ 2006-04-12 15:41 Evan 閱讀(1638) | 評論 (3)編輯 收藏

         摘要:   Everything is meaningless...假設(shè)你突然死掉,世界將會(huì)怎樣?世界將一樣絢麗,地球轉(zhuǎn)的一樣快,太陽系每天在宇宙中換一個(gè)位置。大海還是大海,波濤還是波濤,一樣的花開花落,潮起潮落。...你是多么可憐的小蟲子,在活著的短暫歲月里,在最美好的青春里,都不曾快樂過,用盡心力去聚集一大堆外在和心靈沒有關(guān)系的小東西,只是出于對未來的沒有信心,小小的心靈在接近熄滅的一天還在發(fā)出那個(gè)愚蠢的聲音,讓你忙碌,讓你憂慮的聲音:我要,我還要。天底下充滿了這樣的小蟲子,當(dāng)一個(gè)離開了,又有一個(gè)來了,做著同樣的事情,洶涌著同樣的小小念頭,受著同樣的煎熬。于是上帝要感慨了:虛空的虛空,凡事都是虛空。已有的事,后必再有;已行的事,后必再行。日光之下,并無新事。
      ...
      不要憂慮“不要為明天憂慮,天上的飛鳥,不耕種也不收獲,上天尚且要養(yǎng)活它,田野里的百合花,從不憂慮它能不能開花,是不是可以開得和其它一樣美,但是它就自然的開花了,開得比所羅門皇冠上的珍珠還美。你呢,憂慮什么呢? 人比飛鳥和百合花貴重多了,上帝會(huì)棄你不顧嗎?”  閱讀全文
    posted @ 2006-04-09 22:13 Evan 閱讀(983) | 評論 (0)編輯 收藏

         摘要: 推薦兩款純Java的SVN Web Client軟件。其安裝使用均比ViewVC要好!  閱讀全文
    posted @ 2006-04-06 00:30 Evan 閱讀(19277) | 評論 (21)編輯 收藏

         摘要: 前幾天好奇,也剛好得了點(diǎn)空閑,然后就想看看ViewVC對Subversion的支持程度,于是就想裝個(gè)玩玩。好死不死的,在我的VMWare Workstation上剛好有個(gè)Windows Server 2003,心想,就它吧,可就這么一偷懶,折騰了我好幾天,最終還是只能算將就著把它給裝上了。  閱讀全文
    posted @ 2006-04-05 00:28 Evan 閱讀(7695) | 評論 (5)編輯 收藏

    常常能從galeer(嘎荔兒)的網(wǎng)絡(luò)日志里聽到一些比較好聽的歌曲,并且那些點(diǎn)評也不錯(cuò)。今天聽到U2 - With or Withou You,首先,這首歌還真不錯(cuò);其次,不知是這首歌原來就帶的呢,還是galeer自己加上了這樣幾句詩:

    我雖然行過死蔭的幽谷,
    也不怕遭害;
    因?yàn)槟闩c我同在;
    你的杖,你的竿,都安慰我。

    --《詩篇第二十三篇第四節(jié)》

    當(dāng)然,一開始我不知道這是《舊約全書·詩篇》中的內(nèi)容,于是就Google了一把,找到下面這篇文章《因?yàn)槟闩c我同在》:


    我去一個(gè)鄉(xiāng)村教會(huì)講道,在接待的弟兄家休息??匆姷苄值膬鹤訉W(xué)習(xí)很用功,很是喜愛。我請小朋友將他的語文課本借給我看。這是人教版小學(xué)四年級語文課本。當(dāng)中有一篇文章吸引了我——

    1989 年美國洛杉磯大地震,30萬人在不到4分鐘時(shí)間里受到不同程度的傷害。這其間一個(gè)小學(xué)的慘況讓人心酸。多少孩子的父母因在地震中痛失愛子而哀聲聞天,面對 地震后的學(xué)校廢墟只能絕望離去。但一個(gè)父親卻在廢墟中不斷地挖掘?qū)ふ易约耗遣牌邭q的叫阿曼達(dá)的兒子。救火隊(duì)長擋住他,“太危險(xiǎn)了,隨時(shí)可能發(fā)生大爆炸,請 你離開。”別的學(xué)生家長也勸說,“太晚了,沒有希望了。”可這位父親不顧這些勸阻,在廢墟中不斷地尋找。就在他挖了整整八個(gè)小時(shí)后,父親聽見瓦礫堆底下傳 出他十分熟悉的聲音,“爸爸,是你嗎?”這時(shí)他發(fā)現(xiàn)有14個(gè)孩子在當(dāng)中,因?yàn)檫@是在教室墻角的位置,當(dāng)房頂塌下時(shí)架成大三角形,孩子們才沒被砸著。“我告 訴同學(xué)們不要害怕,說只要我爸爸活著就一定會(huì)來救我,也能救大家。因?yàn)槟阏f過,不論發(fā)生什么,你總會(huì)和我在一起!”孩子對爸爸說。“爸爸,先讓我的同學(xué)出 去吧,我知道你會(huì)跟我在一起,我不怕。不論發(fā)生了什么,我知道你總會(huì)跟我在一起。”

    14個(gè)孩子獲救了!

    我們不禁會(huì)問,如果因?yàn)榇蟊ǖ奈kU(xiǎn)而絕望地放棄,如果這個(gè)父親和其他的家長一樣絕望地離開,如果阿曼達(dá)沒有“因?yàn)槟闩c我同在”的信念,那結(jié)果又將如何?

    我想說的是,絕望讓生命失去,希望使生命存留。

    詩人說,“因?yàn)槟闩c我同在。”(詩篇23:3)這樣的信心使詩人在人生的黑夜里依然有生命的曙光,在人生的冬天里可憑信宣告說,冬天來了,上帝的春天也不再遙遠(yuǎn)。

    “因?yàn)槲遗c你同在,要拯救你。這是耶和華說的。”(耶利米書1:8)

        阿曼達(dá)對父親單純的信念應(yīng)一如我們對天上的父親執(zhí)著的信仰。



    是啊,“絕望讓生命失去,希望使生命存留”,不過呢,對于我這個(gè)不信教的人來說,大可抱著象故事中的小阿曼達(dá)相信他父親只要活著就一定會(huì)來救他的希望一樣,也不一定非要抱著耶和華會(huì)來救我們的希望的。不過,不管信什么教,基督也好,佛陀也好,其實(shí)所有經(jīng)典中的智慧都是值得學(xué)習(xí)的;當(dāng)然,如果你在這個(gè)浮躁的物質(zhì)社會(huì)中實(shí)在找不到可以依賴的東西時(shí),信個(gè)把教也未嘗不可。
    posted @ 2006-04-01 21:33 Evan 閱讀(581) | 評論 (0)編輯 收藏

         摘要: SVN會(huì)取代CVS嗎?這個(gè)雖然不是我們這種小程序員能決定的大事,但學(xué)學(xué)總無妨吧,這里有一些我搜集的資料。  閱讀全文
    posted @ 2006-03-23 23:55 Evan 閱讀(3193) | 評論 (0)編輯 收藏

         摘要: 你是不是為了高的測試覆蓋度而在為每個(gè)函數(shù)添加多個(gè)測試方法,甚至連getX()和setX()都不放過呢?或者,你一看到覆蓋度達(dá)到100%的代碼,景仰之心就開始“有如滔滔江水綿綿不絕,又有如黃河泛濫,一發(fā)不可收拾”了呢?那么,你應(yīng)該讀讀Andrew Glover在最近的developerWorks上發(fā)表的這篇文章。  閱讀全文
    posted @ 2006-03-18 23:23 Evan 閱讀(1204) | 評論 (0)編輯 收藏

         摘要: 《Java Threads》的第5章“Minimal Synchronization Techniques”,是這本書中到現(xiàn)在我認(rèn)為最差的一章了,當(dāng)然主要是我不喜歡JDK 1.5新推出的Atomic Class,而這一章卻花了不少篇章來介紹,且牽強(qiáng)地改造打字程序,又語焉不詳?shù)刂赋鲞@種改造的困難之處和可能帶來的副作用,但卻又不能從代碼的實(shí)際運(yùn)行中看到這種副作用,很有誤導(dǎo)初學(xué)者的嫌疑。不過,我想,沒有哪個(gè)初學(xué)者會(huì)冒風(fēng)險(xiǎn)為了用Atomic Class而將原本簡單明了的算法改造得如此晦澀難懂,并且還有潛在的出錯(cuò)風(fēng)險(xiǎn)。所以,對于Atomic Class,我建議跳過不讀,絕對沒有什么損失。不過對于其中“5.1.3 Double-Checked Locking”和“5.3 Thread Local Variables”這兩節(jié)倒要著重讀一讀,尤其是Thread Local,應(yīng)該說是Java中一個(gè)比較重要的多線程工具。  閱讀全文
    posted @ 2006-03-11 23:11 Evan 閱讀(1656) | 評論 (0)編輯 收藏

         摘要: 快來看“洋本山”怎樣忽悠一個(gè)只想買一把錘子的人最后買了一個(gè)工具工廠的建造工廠的通用建造工廠。很別扭是吧,但如果你是個(gè)開發(fā)Web應(yīng)用的Java程序員,你也許已經(jīng)或者正在被忽悠。  閱讀全文
    posted @ 2006-03-11 17:04 Evan 閱讀(5785) | 評論 (23)編輯 收藏

    看到《Java Threads》第5章,介紹了JDK 1.5新加的一些所謂原子類(Atomic Classes),總感覺有點(diǎn)為原子而原子,實(shí)際操作中,又有多少人會(huì)為了少許的性能提升而刻意去用這些別扭的操作而放棄直觀的synchronize關(guān)鍵字或者Lock類呢?不過,這里不是想討論這個(gè),而是當(dāng)其用Atomic Classes來改造它的打字程序后,解釋用原子類只是保證類似遞增、遞減、賦值等操作的原子性,而不能保證其所在的方法一定是線程安全的,然后說,有可能按鍵事件的處理可能需要等待resetScore()處理完才能執(zhí)行,而這會(huì)導(dǎo)致錯(cuò)誤的評分(被當(dāng)成多敲了鍵)。由于前幾章的內(nèi)容相對比較簡單易懂,所以也沒有很仔細(xì)的運(yùn)行那些例子。這里為了驗(yàn)證一下,就運(yùn)行了一下第4章的例子,然后發(fā)現(xiàn),基本上第一次的評分總是錯(cuò)的。這就引起了我的注意,因?yàn)椋话闱闆r下,如果是race condition導(dǎo)致的錯(cuò)誤是很難重現(xiàn)的,這么明顯的錯(cuò)誤很可能是程序邏輯上的錯(cuò)誤。仔細(xì)看了一下代碼,發(fā)現(xiàn)在start按鈕的事件處理方法里,有下面這樣一段代碼:
    startButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                    displayCanvas.setDone(false);
                    producer.setDone(false);
                    startButton.setEnabled(false);
                    stopButton.setEnabled(true);
                    feedbackCanvas.setEnabled(true);
                    feedbackCanvas.requestFocus();
                    score.resetScore();
                }
            });
    注意重置成績的調(diào)用放在了最后,此時(shí),隨機(jī)生成字符的線程應(yīng)該被喚醒并產(chǎn)生了第一個(gè)字符,然后,resetScore()將需要輸入的字符又設(shè)成了-1,所以,當(dāng)你第一次輸入字符時(shí),總是被認(rèn)為是多擊了一次鍵而扣1分:(。既然這樣,那停止然后再啟動(dòng)也應(yīng)該會(huì)發(fā)生這個(gè)錯(cuò)誤啊。而事實(shí)上的確是這樣。我想,這不應(yīng)該看做是race condition吧,有什么樣的同步技術(shù)能夠避免這個(gè)問題呢?除非另外弄個(gè)標(biāo)志,當(dāng)成績沒有被重置前,不能產(chǎn)生第一個(gè)字符。當(dāng)然,這是不需要的,只要將score.resetScore()放到第一句就可以了。

    然后又運(yùn)行了第3章的例子,發(fā)現(xiàn)基本上沒有這個(gè)問題。難道第3章的代碼是正確的?打開源代碼一看,重置成績的方法還是放在最后,那這里為什么又是正確的呢?我想,大約是第3章的例子中,每次點(diǎn)擊start按鈕,都重新創(chuàng)建一個(gè)線程對象的原因吧。由于創(chuàng)建對象和初始化線程需要一定的時(shí)間,剛好給了主線程重置成績的機(jī)會(huì)。

    不知道作者有意為之呢,還是疏忽,不過,這樣的錯(cuò)誤不能算是race condition的例子。
    posted @ 2006-03-09 22:11 Evan 閱讀(847) | 評論 (0)編輯 收藏

    第3章主要介紹了數(shù)據(jù)的同步(Data Synchronization),這一章則主要介紹線程之間的同步方法(Thread Notification),同樣包括傳統(tǒng)的wait-and-notify方法和JDK 1.5新推出的Condition Variable。在多線程編程中,數(shù)據(jù)同步和線程同步是兩個(gè)最基本也是最關(guān)鍵的部分。
    《Java Threads》一書中通過考察打字程序中當(dāng)按下start和stop按鈕后,每次都創(chuàng)建兩個(gè)新的線程的效率問題來引入線程同步的概念,當(dāng)然不是線程同步的主要用處。不過,教科書歸教科書,實(shí)際運(yùn)用則又是另一回事。所以,通過書本學(xué)習(xí)語法,通過實(shí)踐來獲得運(yùn)用經(jīng)驗(yàn)。

    4.1 Wait and Notify

    1. 等待/喚醒類似于Solaris或POSIX中的條件變量(conditon variables),或者Windows中的事件變量(evant variable)或者信號量(signal),用于某個(gè)/多個(gè)線程暫停等待某個(gè)條件的滿足,而該條件將由其它線程來設(shè)置的情況。
    2. 在Java中,就像每個(gè)對象有一個(gè)鎖之外,任何對象都可以提供等待/喚醒的機(jī)制。就像Java中的synchronized總是表示獲得某個(gè)具體對象的鎖一樣,wait和notify也總是等待某個(gè)具體的對象,并由該對象喚醒;同樣,獲得某個(gè)對象上的鎖不一定是該對象需要同步一樣,等待和喚醒的條件也不一定是與之綁定的對象。
    3. Java中wait-and-notify的幾個(gè)方法:
    void wait(): 使當(dāng)前線程處于等待狀態(tài),直到其它線程調(diào)用了nofity()或者notifyAll()方法為止。
    void wait(long timeout): 使當(dāng)前線程處于等待狀態(tài),直到其它線程調(diào)用了nofity()或者notifyAll()方法,或者超過了指定的時(shí)間(單位為ms)為止
    void wait(long timeout, int nanos):與wait(long)一樣,只是在某些JVM中可以精確到奈秒。
    void notify(): 喚醒一個(gè)正在等待該對象的線程。
    void notifyAll(): 喚醒所有正在等待該對象的線程。
    注意:任何等待和喚醒方法都必須在與之對應(yīng)的對象的同步方法或同步塊里調(diào)用。即:wait-and-notify必須和與之對應(yīng)的synchronized關(guān)鍵詞一起使用的。
    4. wait()和sleep()的主要區(qū)別:
      1) sleep()可以在任何地方調(diào)用,而wait()需要在同步方法或同步塊中調(diào)用;
      2) 進(jìn)入wait()函數(shù)時(shí),JVM會(huì)自動(dòng)釋放鎖,而當(dāng)從wait()返回即被喚醒時(shí),又會(huì)自動(dòng)獲得鎖;而sleep()沒有這個(gè)功能,因此如果在wait()的地方用sleep()代替,則會(huì)導(dǎo)致相應(yīng)的nofity()方法在等待時(shí)不可能被觸發(fā),因?yàn)閚otify()必須在相應(yīng)的同步方法或同步塊中,而此時(shí)這個(gè)鎖卻被sleep()所在的方法占用。也就是說,wait-and-notify不可能與sleep()同時(shí)使用。

    4.1.1 The Wait-and-Notify Mechanism and Synchronization
    1. 這一節(jié)詳細(xì)的講解了wait-and-notify機(jī)制和synchronized的關(guān)系,主要是兩點(diǎn):1)wait-and-notify必須和synchronized同時(shí)使用;2)wait()會(huì)自動(dòng)釋放和獲取鎖;
    2. 這一節(jié)中舉了一個(gè)例子用來解釋可能存在當(dāng)條件被不滿足時(shí)也有可能被喚醒的情況:
      1) 線程T1調(diào)用一個(gè)同步方法;
      2) T1檢測狀態(tài)變量,發(fā)現(xiàn)其不滿足條件;
      3) T1調(diào)用wait(),并釋放鎖;
      4) 線程T2調(diào)用另外一個(gè)同步方法,獲得鎖;
      5) 線程T3調(diào)用另外一個(gè)同步方法,由于T2獲得了鎖,所以處于等待狀態(tài);
      6) T2修改狀態(tài)變量,使其滿足條件,并調(diào)用notify()方法;
      7) T3獲得鎖,然后處理數(shù)據(jù),并將狀態(tài)變量又設(shè)置為不滿足條件的狀態(tài);
      8) T3處理完畢返回;
      9) T1被喚醒,但實(shí)際上此時(shí)條件并不滿足。
    這個(gè)例子剛好印證了《Effective Java》中"Item 50: Never invoke wait outside a loop"和《Practical Java》中"實(shí)踐54:針對wait()和notifyAll()使用旋鎖(spin locks)"。即總是用下面這種方式來調(diào)用wait():
        synchronized(obj) {
    while(<condition does not hold>)
    wait();
    
    ... // Perform action appropriate to condition }
    或者象《Practical Java》中一樣:
        synchronized(obj) {
    while(<condition does not hold>) {
    try {
    wait();
    } catch (InterruptedException e) {}
    }

    ... // Perform action appropriate to condition }
    3. 調(diào)用wait()的線程T可能在以下幾種情況被喚醒:
      1) 其它線程調(diào)用了notify(),而剛好線程T得到了通知;
      2) 其它線程調(diào)用了notifyAll();
      3) 其它線程中斷了線程T;
      4) 由于JVM的原因,導(dǎo)致了spurious wakeup。

    4.1.2 wait(), notify(), and notifyAll()
    1. 正像多個(gè)線程等待同一對象上的鎖,當(dāng)鎖釋放時(shí),無法確定哪個(gè)線程會(huì)得到那個(gè)鎖一樣;當(dāng)有多個(gè)線程在wait()時(shí),當(dāng)另外一個(gè)線程調(diào)用nofity()的時(shí)候,也不能確定哪個(gè)線程會(huì)被喚醒; 2. 因此在《Practical Java》的"實(shí)踐53:優(yōu)先使用notifyAll()而非notify()"建議的一樣,結(jié)合實(shí)踐54,可以比較好的解決線程喚醒的問題。

    4.1.3 Wait-and-Notify Mechanism with Synchronized blocks
    再次強(qiáng)調(diào)必須在同一個(gè)對象的synchronized方法或塊內(nèi)調(diào)用該對象上的wait和notify方法。

    4.2 Condition Variables

    1. 就像上面反復(fù)強(qiáng)調(diào)的一樣,wait-and-notify機(jī)制是與特定對象及其上的鎖是綁定在一起的,鎖和喚醒對象不能分開,這在某些情況下不是很方便;
    2. JDK 1.5提供Condition接口來提供與其它系統(tǒng)幾乎一致的condition variables機(jī)制;
    3. Condition對象由Lock對象的newCondition()方法生成,從而允許一個(gè)鎖產(chǎn)生多個(gè)條件變量,可以根據(jù)實(shí)際情況來等待不同條件;
    4. 該書的例子沒有什么特別的實(shí)際意義,但JDK 1.5文檔中提供了一個(gè)例子,能充分說明使用Condition Variables使得程序更加清晰易讀,也更有效率:
    class BoundedBuffer {
    final Lock lock = new ReentrantLock();
    final Condition notFull = lock.newCondition();
    final Condition notEmpty = lock.newCondition(); final Object[] items = new Object[100]; int putptr, takeptr, count;

    public void put(Object x) throws InterruptedException {
    lock.lock();
    try {
    while (count == items.length)
    notFull.await();
    items[putptr] = x;
    if (++putptr == items.length) putptr = 0;
    ++count;
    notEmpty.signal();
    } finally {
    lock.unlock();
    }
    }
    public Object take() throws InterruptedException {
    lock.lock();
    try {
    while (count == 0)
    notEmpty.await();
    Object x = items[takeptr];
    if (++takeptr == items.length) takeptr = 0;
    --count;
    notFull.signal();
    return x;
    } finally {
    lock.unlock();
    }
    }
    }
    具體的說明請參考JDK 1.5的文檔。
    5. 除了用lock和await-and-signal來代替synchronized和wait-and-notify外,其語義和機(jī)制基本一樣。await()在進(jìn)入前也會(huì)自動(dòng)釋放鎖,然后再返回前重新獲得鎖;
    6. 使用Condition Variables的原因:
      1) 如果使用Lock對象,則必須使用condition variables;
      2) 每個(gè)Lock對象可以創(chuàng)建多個(gè)condition variable.
    posted @ 2006-03-06 22:21 Evan 閱讀(825) | 評論 (0)編輯 收藏

    主站蜘蛛池模板: 国产特黄特色的大片观看免费视频| 亚洲美国产亚洲AV| 国产线视频精品免费观看视频| 亚洲国产精品综合久久网络| 成人免费网站视频www| 亚洲精品亚洲人成在线观看下载 | 四虎免费久久影院| 亚洲AV无码国产剧情| 日韩免费视频在线观看| 国内成人精品亚洲日本语音| 国产中文字幕免费| 一出一进一爽一粗一大视频免费的| 久久影院亚洲一区| 亚洲成人免费在线| 国产日本亚洲一区二区三区| 免费观看美女裸体网站| fc2免费人成为视频| 水蜜桃亚洲一二三四在线| 美女网站免费福利视频| 国产午夜亚洲精品不卡免下载 | 青青草原精品国产亚洲av| 免费观看的毛片大全| 色婷婷精品免费视频| 亚洲精品乱码久久久久久中文字幕 | AV无码免费永久在线观看| 亚洲免费福利在线视频| 亚洲av麻豆aⅴ无码电影| 日韩成人免费视频| 中文字幕无码精品亚洲资源网久久| 亚洲AV无码之日韩精品| 久久午夜夜伦鲁鲁片免费无码| 33333在线亚洲| 亚洲人成人77777网站| 人与禽交免费网站视频| 特a级免费高清黄色片| 久久久国产精品亚洲一区| 四虎成人精品在永久免费| 一区二区三区四区免费视频| 国产精品亚洲а∨无码播放麻豆 | 免费国产不卡午夜福在线| 久久青草免费91线频观看不卡|