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

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

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

    2010年12月17日

    前兩天休眠后機(jī)器非正常關(guān)機(jī),重新啟動(dòng)后運(yùn)行eclipse。悲催的發(fā)現(xiàn)eclipse 無(wú)法啟動(dòng)了。每次雙擊啟動(dòng)后,確定完workspace后,顯示啟動(dòng)畫(huà)面,沒(méi)過(guò)一會(huì)就進(jìn)入灰色無(wú)響應(yīng)狀態(tài)。啟動(dòng)畫(huà)面始終停留在Loading workbench狀態(tài)。反復(fù)重啟,狀態(tài)依舊。嘗試解決。

    搜索了一下,應(yīng)該是非正常關(guān)機(jī)導(dǎo)致eclipse工作區(qū)的文件狀態(tài)錯(cuò)誤導(dǎo)致。在工作區(qū)目錄中,有一個(gè).metadata目錄,里面是工作區(qū)及各插件的信息,刪除此目錄可以解決問(wèn)題。

    為保險(xiǎn)起見(jiàn),將.metadata改名移動(dòng)到/tmp目錄,再重啟eclipse,果然可以正常啟動(dòng)eclipse了,但原來(lái)工作區(qū)的配置和項(xiàng)目信息也都消失,直接顯示的是歡迎界面。

    如何恢復(fù)原來(lái)的project配置呢?嘗試對(duì)比了當(dāng)前的.metadata和之前備份的那個(gè)目錄,發(fā)現(xiàn)缺少了很多配置文件。試著一點(diǎn)點(diǎn)恢復(fù)一些目錄,但效 果不理想。因?yàn)椴恢滥男┪募?目錄)可以恢復(fù),哪些恢復(fù)會(huì)帶來(lái)問(wèn)題。將備份的整個(gè)目錄恢復(fù)試試?Eclipse又回到了無(wú)法啟動(dòng)的狀態(tài)了。

    怎么辦?這時(shí)想到啟動(dòng)停止時(shí)顯示的狀態(tài):"Loading workbench",看來(lái)和這個(gè)workbench插件有關(guān)。查看原來(lái)的.metadata/.plugins目錄,在眾多文件夾中
    com.collabnet.subversion.merge          org.eclipse.search
    org.eclipse.compare                           org.eclipse.team.core
    org.eclipse.core.resources                  org.eclipse.team.cvs.core
    org.eclipse.core.runtime               org.eclipse.team.ui
    org.eclipse.debug.core                 org.eclipse.ui.ide
    org.eclipse.debug.ui                   org.eclipse.ui.intro
    org.eclipse.dltk.core                    org.eclipse.ui.views.log
    org.eclipse.dltk.core.index.sql.h2     org.eclipse.ui.workbench
    org.eclipse.dltk.ui                           org.eclipse.ui.workbench.texteditor
    org.eclipse.epp.usagedata.recording    org.eclipse.wb.discovery.core
    org.eclipse.jdt.core                             org.eclipse.wst.internet.cache
    org.eclipse.jdt.ui                                 org.eclipse.wst.jsdt.core
    org.eclipse.ltk.core.refactoring          org.eclipse.wst.jsdt.ui
    org.eclipse.ltk.ui.refactoring            org.eclipse.wst.jsdt.web.core
    org.eclipse.m2e.core                    org.eclipse.wst.sse.ui
    org.eclipse.m2e.logback.configuration  org.eclipse.wst.validation
    org.eclipse.mylyn.bugzilla.core        org.eclipse.wst.xml.core
    org.eclipse.mylyn.tasks.ui             org.tigris.subversion.subclipse.core
    org.eclipse.php.core                   org.tigris.subversion.subclipse.graph
    org.eclipse.php.ui                     org.tigris.subversion.subclipse.ui

    發(fā)現(xiàn)了兩個(gè): org.eclipse.ui.workbenchorg.eclipse.ui.workbench.texteditor

    不管三七二十一,刪了這兩個(gè)目錄,重新啟動(dòng)eclipse。正常啟動(dòng)且原項(xiàng)目信息正確加載。
    posted @ 2012-11-11 14:15 胡鵬 閱讀(6455) | 評(píng)論 (7)編輯 收藏

    最近團(tuán)隊(duì)遇到一個(gè)案例。看似很小的事情,但仔細(xì)研究起來(lái),徹底分析,每一個(gè)環(huán)節(jié)都沒(méi)做好,細(xì)節(jié)部分糟糕得一塌糊涂,最后導(dǎo)致一件事情的結(jié)果:完全失敗。

    經(jīng)常有人在聊起公司的時(shí)候問(wèn)我,你現(xiàn)在最擔(dān)心的事情有哪些? 我當(dāng)然會(huì)重點(diǎn)提到團(tuán)隊(duì)。不過(guò)在談及團(tuán)隊(duì)的時(shí)候,我又最擔(dān)心在「細(xì)節(jié)」問(wèn)題上做不好。

    細(xì)節(jié)就是競(jìng)爭(zhēng)力,尤其是對(duì)小團(tuán)隊(duì)來(lái)說(shuō),小團(tuán)隊(duì)更應(yīng)該注重細(xì)節(jié)問(wèn)題。大一點(diǎn)的公司可以追究責(zé)任人,靠流程、靠制度,靠各級(jí)評(píng)審等等一系列的「成本」來(lái)提升細(xì)節(jié)能力。小一點(diǎn)的公司或者團(tuán)隊(duì)怎么辦? 恐怕只有依賴每個(gè)人的能力和責(zé)任心了。

    細(xì)節(jié)也是鍛煉人的能力的地方,搞清楚每一個(gè)細(xì)節(jié),將每一個(gè)細(xì)節(jié)涉及到的背景知識(shí)和技能掌握好,能力自然也就會(huì)得到提升。繼而,著手做更大的事情也不 會(huì)手忙腳亂。相反,做不好細(xì)節(jié)和小事的人,如果總?cè)轮觥钢匾沟氖虑椋龈小柑魬?zhàn)」的事情,這樣的事情真的到你面前,真的能接住么?

    為什么我們?cè)诩?xì)節(jié)上做不好?

    對(duì)細(xì)節(jié)問(wèn)題不夠重視 一件事情到了自己這里,頭腦中先入為主認(rèn)為只是一件小事,是一件簡(jiǎn)單的事情。這樣,當(dāng)然就不會(huì)給予足夠的重視。小事不一定不重要,小事不一定意味著做起來(lái)就簡(jiǎn)單。

    對(duì)事情復(fù)雜度缺乏認(rèn)知 不就是給客戶寫(xiě)一封電子郵件么? 不就是用 HTML 寫(xiě)一個(gè)頁(yè)面么? 不就是做一則橫幅廣告么? 那么,這些事情真的簡(jiǎn)單么? 為什么別人為客戶寫(xiě)的郵件打開(kāi)率更高? 為什么別人寫(xiě)的頁(yè)面更容易被搜索引擎收錄? 為什么別人做的廣告轉(zhuǎn)化率更好? 背后涉及到哪些知識(shí)? 不想研究一下么? 不能研究一下么?

    對(duì)細(xì)節(jié)缺乏耐心 草草了事,應(yīng)付了事,遇到問(wèn)題馬馬虎虎,輕易得放過(guò)了很多可以讓自己得到成長(zhǎng)的機(jī)會(huì)。「這問(wèn)題我沒(méi)想過(guò)」「這事情我沒(méi)遇到過(guò)」「設(shè)計(jì)稿都改過(guò)兩次了」... 這類借口在任何一個(gè)團(tuán)隊(duì)都很常見(jiàn)。

    缺少責(zé)任心 常常覺(jué)得自己這里做不好,還有別人會(huì)把關(guān)呢。擔(dān)心什么? 可如果所有人都這么想呢? 「文案是產(chǎn)品經(jīng)理的事情,關(guān)我甚么事?」如果你能對(duì)文案也有改進(jìn)意見(jiàn),誰(shuí)說(shuō)以后你就不能做產(chǎn)品經(jīng)理做的事情呢?

    主觀上不認(rèn)可自己的工作 就給我這么一點(diǎn)錢,要我做這么多工作? 問(wèn)題是我們?nèi)绻欢嘧鲆稽c(diǎn)工作,不提升一下自己,又怎么能多一點(diǎn)錢呢?

    為什么細(xì)節(jié)上做不好? 不同人不同的角度還會(huì)有不同的看法。不過(guò)有一點(diǎn)我能肯定,細(xì)節(jié)不會(huì)決定成敗,但做不好細(xì)節(jié),一定會(huì)失敗。

    做好細(xì)節(jié),百事可作。

    posted @ 2012-10-28 16:31 胡鵬 閱讀(236) | 評(píng)論 (0)編輯 收藏
    mac中自帶的jdk并不包含源代碼,所以在eclipse中無(wú)法查看, 需要到apple上去下載,
    https://developer.apple.com/downloads/index.action
    Documentation and developer runtime of "Java for OS X 2012-005". Contains JavaDoc, tools documentation, and native framework headers.
    目前的版本是:Java for OS X 2012-005 Developer Package
    下載下來(lái)后,直接安裝,默認(rèn)設(shè)置就可以了,然后可以建個(gè)link,方便選擇。
    1. sudo -s
    2. cd /System/Library/Frameworks/JavaVM.framework/Home
    3. ln -s /Library/Java/JavaVirtualMachines/1.6.0_35-b10-428.jdk/Contents/Home/docs.jar
    4. ln -s  /Library/Java/JavaVirtualMachines/1.6.0_35-b10-428.jdk/Contents/Home/src.jar
    5. 最后跟windows類似,在eclipse中用command + click點(diǎn)擊查看一個(gè)類的源碼。然后選“add source",選中上面的 src.jar 文件即可
    posted @ 2012-10-16 21:48 胡鵬 閱讀(3786) | 評(píng)論 (0)編輯 收藏
    雖然android安裝完成后會(huì)有一套參考手冊(cè),其中包括了api,但是如果在開(kāi)發(fā)過(guò)程中能查看android的源碼(sdk的源碼),將對(duì)我們學(xué)習(xí)android有一定的幫助.畢竟,有時(shí)候源碼比api文檔更能說(shuō)明問(wèn)題.
        我平常學(xué)習(xí)android用的2.2版本,從網(wǎng)上下載了2.2的源碼(從官方git庫(kù)下載太麻煩,是從網(wǎng)友共享的源碼位置下載的).按照網(wǎng)上的說(shuō)法,我把 解壓后的那一堆文檔放在了android-sdk-root\platforms\android-8\sources目錄下.不過(guò)并沒(méi)有重啟 eclipse.而是通過(guò)這種方法來(lái)做的-----在eclipse中,鼠標(biāo)放在一個(gè)android提供的類上,按下ctrl鍵,會(huì)打開(kāi)一個(gè)新頁(yè)面,提示 找不到對(duì)應(yīng)的類的class或者源文件,但這個(gè)新頁(yè)面上有個(gè)導(dǎo)入源碼的按鈕,點(diǎn)擊之后選擇下載好的source位置,確定后就可以了.
        順便說(shuō)下我下載android源碼的位置:
            http://tech.cncms.com/UploadFiles/20101025/androidsdk2.2_sources.zip

    下載源碼到maven倉(cāng)庫(kù): http://search.maven.org/#search|gav|1|g%3A%22com.google.android%22%20AND%20a%3A%22android%22

    posted @ 2012-09-16 10:15 胡鵬 閱讀(455) | 評(píng)論 (0)編輯 收藏
            離開(kāi)淘寶后,自己創(chuàng)業(yè),產(chǎn)品需要推廣,考慮到當(dāng)今流量最大的聚集在微博上,我們也來(lái)做做微博運(yùn)營(yíng),我是一個(gè)技術(shù)人員,運(yùn)營(yíng)對(duì)于我來(lái)說(shuō),從0開(kāi)始,站在巨人的肩膀上學(xué)習(xí),稍稍總結(jié)了下。

    1. 使用工具:微博第三方插件已經(jīng)提供了很多功能,適合自己的都用起來(lái),這個(gè)我覺(jué)得最節(jié)省我的時(shí)間,其他網(wǎng)上提供的軟件都可以使用,重要是適合自己,安全第一。

    2. 寫(xiě)工具:有很多個(gè)性化需求的時(shí)候,如果變相的不能實(shí)現(xiàn),人為處理太慢太花時(shí)間,我們現(xiàn)在是小創(chuàng)業(yè)團(tuán)隊(duì),很多事情都需要自己做,數(shù)據(jù)增長(zhǎng)慢,在有限的資源下,寫(xiě)工具是非常好的方式,作為技術(shù)人員就直接動(dòng)手寫(xiě),當(dāng)然也需要看看性價(jià)比。


    3.微博定位:
    找好本微博的主題,內(nèi)容一般遵循原則:定制+非定制。定制是指針對(duì)你的目標(biāo)群體來(lái)選擇內(nèi)容,要讓這部分人感興趣,非定制:是指那種適合任何粉絲的內(nèi)容。

     

    例如:我的目標(biāo)群體是女性,我的定制內(nèi)容就有美容、護(hù)膚、服飾搭配、星座、愛(ài)情等女性關(guān)注的話題,非定制的有笑話、經(jīng)典語(yǔ)錄、旅游等大眾類容。根據(jù)內(nèi)容來(lái) 建立話題,如#美容護(hù)膚# #開(kāi)心一笑##XX語(yǔ)錄#等等,我就為自己建立了10個(gè)左右話題,每天的內(nèi)容按照話題來(lái)制作。

     

    4.主要工作流程:(這個(gè)圖是轉(zhuǎn)的)


    5.常用的微博話題(這個(gè)圖片也是轉(zhuǎn)的)



    6. 關(guān)注項(xiàng)目:微博和主動(dòng)@,評(píng)論,私信,群,邀請(qǐng),勛章,策劃產(chǎn)品活動(dòng),參與微活動(dòng)

     

     7.微博運(yùn)營(yíng)最重要的是:一段時(shí)間需要總結(jié)挑選合適的方法執(zhí)行,沒(méi)有效果的去除。

    如:微博發(fā)布時(shí)間/數(shù)量

    我(轉(zhuǎn),不是我)曾在粉絲超過(guò)一萬(wàn)之后就開(kāi)始研究的我的微博改什么時(shí)候發(fā)布,每天發(fā)布多少。我現(xiàn)在粉絲中做了一個(gè)投票:你們一般什么時(shí)候織微博。最后有200多人參加, 我大概劃分了5個(gè)時(shí)段,9-12點(diǎn),12-17點(diǎn) 17-19點(diǎn) 19-22點(diǎn) 22-24點(diǎn) 0-3點(diǎn),做多選擇3個(gè)答案,結(jié)果出來(lái)之后就有個(gè)大概了。接下來(lái)我用一周的時(shí)間從9點(diǎn)—24點(diǎn)之間每1小時(shí)發(fā)布一條信息。總共16條信息,我就分析每條信 息的轉(zhuǎn)發(fā)、回復(fù)數(shù)量,一周之后我就可以摸清粉絲的上網(wǎng)時(shí)間規(guī)律。然后我選擇哪幾個(gè)時(shí)間段重點(diǎn)維護(hù),并在那幾個(gè)時(shí)間段進(jìn)一步研究發(fā)布數(shù)量規(guī)律,我又分為每1小時(shí),每0.5小時(shí)兩個(gè)因素來(lái)研究發(fā)布數(shù)量。



          
    posted @ 2012-03-28 18:28 胡鵬 閱讀(253) | 評(píng)論 (0)編輯 收藏

    JMock是幫助創(chuàng)建mock對(duì)象的工具,它基于Java開(kāi)發(fā),在Java測(cè)試與開(kāi)發(fā)環(huán)境中有不可比擬的優(yōu)勢(shì),更重要的是,它大大簡(jiǎn)化了虛擬對(duì)象的使用。本文中,通過(guò)一個(gè)簡(jiǎn)單的測(cè)試用例來(lái)說(shuō)明JMock如何幫助我們實(shí)現(xiàn)這種孤立測(cè)試。
        我們?cè)跍y(cè)試某類時(shí),由于它要與其他類發(fā)生聯(lián)系,因此往往在測(cè)試此類的代碼中也將與之聯(lián)系的類也一起測(cè)試了。這種測(cè)試,將使被測(cè)試的類直接依賴于其他類,一旦其他類發(fā)生改變,被測(cè)試類也隨之被迫改變。更重要的是,這些其他類可能尚未經(jīng)過(guò)測(cè)試,因此必須先測(cè)試這些類,才能測(cè)試被測(cè)試類。這種情況下,測(cè)試驅(qū)動(dòng)開(kāi)發(fā)成為空談。而如果其他類中也引用了被測(cè)試類,我們到底先測(cè)試哪一個(gè)類?因此,在測(cè)試中,如果我們能將被測(cè)試類孤立起來(lái),使其完全不依賴于其他類的具體實(shí)現(xiàn),這樣,我們就能做到測(cè)試先行,先測(cè)試哪個(gè)類,就先實(shí)現(xiàn)哪個(gè)類,而不管與之聯(lián)系的類是否已經(jīng)實(shí)現(xiàn)。

        虛擬對(duì)象(mock object)就是為此需要而誕生的。它通過(guò)JDK中的反射機(jī)制,在運(yùn)行時(shí)動(dòng)態(tài)地創(chuàng)建虛擬對(duì)象。在測(cè)試代碼中,我們可以驗(yàn)證這些虛擬對(duì)象是否被正確地調(diào)用了,也可以在明確的情況下,讓其返回特定的假想值。而一旦有了這些虛擬對(duì)象提供的服務(wù),被測(cè)試類就可以將虛擬對(duì)象作為其他與之聯(lián)系的真實(shí)對(duì)象的替身,從而輕松地搭建起一個(gè)很完美的測(cè)試環(huán)境。

        JMock是幫助創(chuàng)建mock對(duì)象的工具,它基于Java開(kāi)發(fā),在Java測(cè)試與開(kāi)發(fā)環(huán)境中有不可比擬的優(yōu)勢(shì),更重要的是,它大大簡(jiǎn)化了虛擬對(duì)象的使用。

        本文中,通過(guò)一個(gè)簡(jiǎn)單的測(cè)試用例來(lái)說(shuō)明JMock如何幫助我們實(shí)現(xiàn)這種孤立測(cè)試。有三個(gè)主要的類,User,UserDAO,及UserService。本文中,我們只需測(cè)試UserService,準(zhǔn)備虛擬UserDAO。對(duì)于User,由于本身僅是一個(gè)過(guò)于簡(jiǎn)單的POJO,可以不用測(cè)試。但如果你是一個(gè)完美主義者,也可以使用JMock的虛擬它。在這領(lǐng)域,JMock幾乎無(wú)所不能。

    這里我用到的是:(我用的是maven依賴)

                <dependency>
       <groupId>org.jmock</groupId>
       <artifactId>jmock</artifactId>
       <version>2.5.1</version>
    </dependency>
     
    <dependency>
       <groupId>org.jmock</groupId>
       <artifactId>jmock-junit3</artifactId>
       <version>2.5.1</version>
    </dependency>

    在官方的網(wǎng)站上也有的下載。   地址:  http://jmock.org/dist/jmock-2.5.1-jars.zip

     


    public class User {
    private String name;
    public User() {
    }
    public User(String name) {
    this.name = name;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    }

     UserDAO負(fù)責(zé)與數(shù)據(jù)庫(kù)打交道,通過(guò)數(shù)據(jù)庫(kù)保存、獲取User的信息。盡管我們可以不用知道JMock如何通過(guò)JDK 的反射機(jī)制來(lái)實(shí)現(xiàn)孤立測(cè)試,但至少應(yīng)知道,JDK的反射機(jī)制要求這些在運(yùn)行時(shí)創(chuàng)建的動(dòng)態(tài)類必須定義接口。在使用JMock的環(huán)境中,由于我們要虛擬 UserDAO,意味著UserDAO必須定義接口

    public interface UserDAO {
    public User getUser(Long id);
    }

    public interface UserService {
    public void setUserDAO(UserDAO userDAO);
    public User getUser(Long id);
    }



    public class UserServiceImpl implements UserService {
    private UserDAO userDAO;
    public UserServiceImpl() {
    }
    public void setUserDAO(UserDAO userDAO) {
    this.userDAO = userDAO;
    }
    public User getUser(Long id) {
    return userDAO.getUser(id);
    }
    }


     
    import org.jmock.Expectations;
    import org.jmock.integration.junit3.MockObjectTestCase;

    public class UserServiceTest extends MockObjectTestCase {
    private UserService userService = new UserServiceImpl();
    private UserDAO userDAO = null;
    public UserServiceTest(String testName) {
    super(testName);
    }
    protected void setUp() throws Exception {
    userDAO = mock(UserDAO.class);
    userService.setUserDAO(userDAO);
    }
    public void testGetUser() {
    String name = "lsb";
    final User fakeUser = new User(name);
    checking(new Expectations(){{
                oneOf(userDAO).getUser(1L);
                will(returnValue(fakeUser));
            }});
    User user = userService.getUser(1L);
    assertNotNull(user);
    assertEquals(name, user.getName());
    }
    protected void tearDown() throws Exception {
    }
    }

    posted @ 2012-02-23 21:52 胡鵬 閱讀(865) | 評(píng)論 (0)編輯 收藏
             在開(kāi)發(fā)Android和iPhone應(yīng)用程序時(shí),我們往往需要從服務(wù)器不定的向手 機(jī)客戶端即時(shí)推送各種通知消息,iPhone上已經(jīng)有了比較簡(jiǎn)單的和完美的推送通知解決方案,可是Android平臺(tái)上實(shí)現(xiàn)起來(lái)卻相對(duì)比較麻煩,最近利用 幾天的時(shí)間對(duì)Android的推送通知服務(wù)進(jìn)行初步的研究。
    在Android手機(jī)平臺(tái)上,Google提供了C2DM(Cloudto Device Messaging)服務(wù)。

    Android Cloud to Device Messaging (C2DM)是一個(gè)用來(lái)幫助開(kāi)發(fā)者從服務(wù)器向Android應(yīng)用程序發(fā)送數(shù)據(jù)的服務(wù)。該服務(wù)提供了一個(gè)簡(jiǎn)單的、輕量級(jí)的機(jī)制,允許服務(wù)器可以通知移動(dòng)應(yīng)用程序直接與服務(wù)器進(jìn)行通信,以便于從服務(wù)器獲取應(yīng)用程序更新和用戶數(shù)據(jù)。C2DM服務(wù)負(fù)責(zé)處理諸如消息排隊(duì)等事務(wù)并向運(yùn)行于目標(biāo)設(shè)備上的應(yīng)用程序分發(fā)這些消息。

    使用C2DM框架的要求
    1. 需要Android2.2及以上的系統(tǒng)版本
    2. 使用C2DM功能的Android設(shè)備上需要設(shè)置好Google的賬戶。
    3.  C2DM需要依賴于Google官方提供的C2DM服務(wù)器,由于國(guó)內(nèi)的網(wǎng)絡(luò)環(huán)境,這個(gè)服務(wù)經(jīng)常不可用,如果想要很好的使用,我們的App Server必須也在國(guó)外,這個(gè)恐怕不是每個(gè)開(kāi)發(fā)者都能夠?qū)崿F(xiàn)的

    要使用C2DM來(lái)進(jìn)行Push操作,基本上要使用以下6個(gè)步驟


    (1)注冊(cè):Android設(shè)備把使用C2DM功能的用戶賬戶(比如android.c2dm.demo@gmail.com)和App名稱發(fā)送給C2DM服務(wù)器。

    (2)C2DM服務(wù)器會(huì)返回一個(gè)registration_id值給Android設(shè)備,設(shè)備需要保存這個(gè)registration_id值。

    (3)Android設(shè)備把獲得的registration_id和C2DM功能的用戶賬戶(android.c2dm.demo@gmail.com)發(fā)送給自己的服務(wù)器,不過(guò)一般用戶賬戶信息因?yàn)楹头?wù)器確定好的,所以不必發(fā)送。

    這樣Android設(shè)備就完成了C2DM功能的注冊(cè)過(guò)程,接下來(lái)就可以接收C2DM服務(wù)器Push過(guò)來(lái)的消息了。

    (4)服務(wù)器獲得數(shù)據(jù)。這里圖中的例子Chrome To Phone,服務(wù)器接收到Chrome瀏覽器發(fā)送的數(shù)據(jù)。數(shù)據(jù)也可以是服務(wù)器本地產(chǎn)生的。這里的服務(wù)器是Google AppEngine(很好的一項(xiàng)服務(wù),可惜在國(guó)內(nèi)被屏了),要換成自己的服務(wù)器。服務(wù)器還要獲取注冊(cè)使用C2DM功能的用戶賬戶(android.c2dm.demo@gmail.com)的ClientLogin權(quán)限Auth。

    (5)服務(wù)器把要發(fā)送的數(shù)據(jù)和registration_id一起,并且頭部帶上獲取的Auth,使用POST的方式發(fā)送給C2DM服務(wù)器。

    (6)C2DM服務(wù)器會(huì)以Push的方式把數(shù)據(jù)發(fā)送給對(duì)應(yīng)的Android設(shè)備,Android設(shè)備只要在程序中按之前和服務(wù)器商量好的格式從對(duì)應(yīng)的key中獲取數(shù)據(jù)即可。

    轉(zhuǎn)自:
    posted @ 2011-12-29 17:57 胡鵬 閱讀(1166) | 評(píng)論 (0)編輯 收藏

    地理位置索引支持是MongoDB的一大亮點(diǎn),這也是全球最流行的LBS服務(wù)foursquare 選擇MongoDB的原因之一。我們知道,通常的數(shù)據(jù)庫(kù)索引結(jié)構(gòu)是B+ Tree,如何將地理位置轉(zhuǎn)化為可建立B+Tree的形式,下文將為你描述。

    首先假設(shè)我們將需要索引的整個(gè)地圖分成16×16的方格,如下圖(左下角為坐標(biāo)0,0 右上角為坐標(biāo)16,16):

     

    單純的[x,y]的數(shù)據(jù)是無(wú)法建立索引的,所以MongoDB在建立索引的時(shí)候,會(huì)根據(jù)相應(yīng)字段的坐標(biāo)計(jì)算一個(gè)可以用來(lái)做索引的hash值,這個(gè)值叫做geohash,下面我們以地圖上坐標(biāo)為[4,6]的點(diǎn)(圖中紅叉位置)為例。

    我們第一步將整個(gè)地圖分成等大小的四塊,如下圖:



    劃分成四塊后我們可以定義這四塊的值,如下(左下為00,左上為01,右下為10,右上為11):

    01 11
    00 10

    這樣[4,6]點(diǎn)的geohash值目前為 00

    然后再將四個(gè)小塊每一塊進(jìn)行切割,如下:



    這時(shí)[4,6]點(diǎn)位于右上區(qū)域,右上的值為11,這樣[4,6]點(diǎn)的geohash值變?yōu)椋?011

    繼續(xù)往下做兩次切分:




    最終得到[4,6]點(diǎn)的geohash值為:00110100

    這樣我們用這個(gè)值來(lái)做索引,則地圖上點(diǎn)相近的點(diǎn)就可以轉(zhuǎn)化成有相同前綴的geohash值了。

    我們可以看到,這個(gè)geohash值的精確度是與劃分地圖的次數(shù)成正比的,上例對(duì)地圖劃分了四次。而MongoDB默認(rèn)是進(jìn)行26次劃分,這個(gè)值在建立索引時(shí)是可控的。具體建立二維地理位置索引的命令如下:

    db.map.ensureIndex({point : "2d"}, {min : 0, max : 16, bits : 4})

    其中的bits參數(shù)就是劃分幾次,默認(rèn)為26次。










     

    posted @ 2011-11-25 17:19 胡鵬 閱讀(575) | 評(píng)論 (0)編輯 收藏
         摘要: java中的引用分為4種:String Reference, WeakReference, softReference,PhantomReference  Strong Reference: 我們平常用的最多的就是強(qiáng)引用了 如:String s = new String("opps");這種形式的引用稱為強(qiáng)引用,這種引用有以下幾個(gè)特點(diǎn) 1.強(qiáng)引用可以直接訪問(wèn)目標(biāo)對(duì)象&...  閱讀全文
    posted @ 2011-10-30 11:59 胡鵬 閱讀(1099) | 評(píng)論 (0)編輯 收藏
         摘要:   一、對(duì)ThreadLocal概術(shù)             JDK API 寫(xiě)道: 該類提供了線程局部 (thread-local) 變量。這些變量不同于它們的普通對(duì)應(yīng)物,因?yàn)樵L問(wèn)某個(gè)變量(通過(guò)其 get 或 set 方法)的每個(gè)線程都有自己的局部變量,它獨(dú)立于變量的初始...  閱讀全文
    posted @ 2011-10-29 17:39 胡鵬 閱讀(1442) | 評(píng)論 (0)編輯 收藏
         摘要:        起因:在寫(xiě)java的時(shí)候,經(jīng)常遇到函數(shù)需要返回2個(gè)值或者3個(gè)值,java必須編寫(xiě)一個(gè)Object,來(lái)封裝,但很多應(yīng)用場(chǎng)景只是臨時(shí)使用,構(gòu)建對(duì)象感覺(jué)殺雞用宰牛刀,而其他語(yǔ)言有比較好的實(shí)現(xiàn)方法。(當(dāng)然通過(guò)指針引用可以解決一部分問(wèn)題) 如:一般寫(xiě)法:     Code high...  閱讀全文
    posted @ 2011-10-28 18:35 胡鵬 閱讀(6404) | 評(píng)論 (0)編輯 收藏
         摘要:     java.util.concurrent包分成了三個(gè)部分,分別是:                        ...  閱讀全文
    posted @ 2011-10-12 17:25 胡鵬 閱讀(2442) | 評(píng)論 (0)編輯 收藏
          不復(fù)制內(nèi)容了,可以看戲如下鏈接,還是有很多值得看的東東,有空看下。~

        
        http://terryblog.blog.51cto.com/1764499/547777
    posted @ 2011-07-13 20:12 胡鵬 閱讀(250) | 評(píng)論 (0)編輯 收藏


    申請(qǐng)一個(gè)Android Maps API Key

    1.找到你的debug.keystore文件所在的路徑:
    證書(shū)的一般路徑為:打開(kāi)eclipse,選擇Windows———>Preference———>Android———>Build,其中Default debug  keystore的值便是debug.keystore的路徑(windows的一般在 C:\Documents and Settings\當(dāng)前用戶\.android下找到debug.keystore)
    2.在命令提示符中執(zhí)行: keytool -list -keystore debug.keystore  (keytool是java一個(gè)命令,在%java_home%\bin里可以看到)
    需要輸入密碼:android
    然后就會(huì)得到MD5的值,進(jìn)入
    http://code.google.com/intl/zh-CN/android/add-ons/google-apis/maps-api-signup.html ,根據(jù)MD5值獲取MAPS API KEY(前提是你必須有一個(gè)google賬戶)
    posted @ 2011-06-18 16:37 胡鵬 閱讀(994) | 評(píng)論 (0)編輯 收藏
          使input組件的絕對(duì)位置覆蓋select組件的選擇框,當(dāng)select的狀態(tài)發(fā)生改變的時(shí)候,使用this.parentNode.nextSibling.value=this.value把select所選擇的值賦給input.

    <HTML> 
    <HEAD> 
    <META http-equiv='Content-Type' content='text/html; charset=gb2312'> 
    <TITLE>可輸入的下拉框</TITLE> 
    </HEAD> 
    <BODY > 
     
    <div style="position:relative;"> 
    <span style="margin-left:100px;width:18px;overflow:hidden;"> 
    <select style="width:118px;margin-left:-100px" onchange="this.parentNode.nextSibling.value=this.value"> 
    <option value="<option value="<option value="WEB開(kāi)發(fā)者"> WEB開(kāi)發(fā)者 </option> 
    </select></span><input name="box" style="width:100px;position:absolute;left:0px;"> 
    </div> 
    </BODY></HTML> 

    單例創(chuàng)建模式是一個(gè)通用的編程習(xí)語(yǔ)。和多線程一起使用時(shí),必需使用某種類型的同步。在努力創(chuàng)建更有效的代碼時(shí),Java 程序員們創(chuàng)建了雙重檢查鎖定習(xí)語(yǔ),將其和單例創(chuàng)建模式一起使用,從而限制同步代碼量。然而,由于一些不太常見(jiàn)的 Java 內(nèi)存模型細(xì)節(jié)的原因,并不能保證這個(gè)雙重檢查鎖定習(xí)語(yǔ)有效。它偶爾會(huì)失敗,而不是總失敗。此外,它失敗的原因并不明顯,還包含 Java 內(nèi)存模型的一些隱秘細(xì)節(jié)。這些事實(shí)將導(dǎo)致代碼失敗,原因是雙重檢查鎖定難于跟蹤。在本文余下的部分里,我們將詳細(xì)介紹雙重檢查鎖定習(xí)語(yǔ),從而理解它在何處失效。

    單例創(chuàng)建習(xí)語(yǔ)

    要理解雙重檢查鎖定習(xí)語(yǔ)是從哪里起源的,就必須理解通用單例創(chuàng)建習(xí)語(yǔ),如清單 1 中的闡釋:


    清單 1. 單例創(chuàng)建習(xí)語(yǔ)
                            import java.util.*;
                class Singleton
                {
                private static Singleton instance;
                private Vector v;
                private boolean inUse;
                private Singleton()
                {
                v = new Vector();
                v.addElement(new Object());
                inUse = true;
                }
                public static Singleton getInstance()
                {
                if (instance == null)          //1
                instance = new Singleton();  //2
                return instance;               //3
                }
                }
                

    此類的設(shè)計(jì)確保只創(chuàng)建一個(gè) Singleton 對(duì)象。構(gòu)造函數(shù)被聲明為 privategetInstance() 方法只創(chuàng)建一個(gè)對(duì)象。這個(gè)實(shí)現(xiàn)適合于單線程程序。然而,當(dāng)引入多線程時(shí),就必須通過(guò)同步來(lái)保護(hù) getInstance() 方法。如果不保護(hù) getInstance() 方法,則可能返回 Singleton 對(duì)象的兩個(gè)不同的實(shí)例。假設(shè)兩個(gè)線程并發(fā)調(diào)用 getInstance() 方法并且按以下順序執(zhí)行調(diào)用:

    1. 線程 1 調(diào)用 getInstance() 方法并決定 instance 在 //1 處為 null

    2. 線程 1 進(jìn)入 if 代碼塊,但在執(zhí)行 //2 處的代碼行時(shí)被線程 2 預(yù)占。

    3. 線程 2 調(diào)用 getInstance() 方法并在 //1 處決定 instancenull

    4. 線程 2 進(jìn)入 if 代碼塊并創(chuàng)建一個(gè)新的 Singleton 對(duì)象并在 //2 處將變量 instance 分配給這個(gè)新對(duì)象。

    5. 線程 2 在 //3 處返回 Singleton 對(duì)象引用。

    6. 線程 2 被線程 1 預(yù)占。

    7. 線程 1 在它停止的地方啟動(dòng),并執(zhí)行 //2 代碼行,這導(dǎo)致創(chuàng)建另一個(gè) Singleton 對(duì)象。

    8. 線程 1 在 //3 處返回這個(gè)對(duì)象。

    結(jié)果是 getInstance() 方法創(chuàng)建了兩個(gè) Singleton 對(duì)象,而它本該只創(chuàng)建一個(gè)對(duì)象。通過(guò)同步 getInstance() 方法從而在同一時(shí)間只允許一個(gè)線程執(zhí)行代碼,這個(gè)問(wèn)題得以改正,如清單 2 所示:


    清單 2. 線程安全的 getInstance() 方法
                            public static synchronized Singleton getInstance()
                {
                if (instance == null)          //1
                instance = new Singleton();  //2
                return instance;               //3
                }
                

    清單 2 中的代碼針對(duì)多線程訪問(wèn) getInstance() 方法運(yùn)行得很好。然而,當(dāng)分析這段代碼時(shí),您會(huì)意識(shí)到只有在第一次調(diào)用方法時(shí)才需要同步。由于只有第一次調(diào)用執(zhí)行了 //2 處的代碼,而只有此行代碼需要同步,因此就無(wú)需對(duì)后續(xù)調(diào)用使用同步。所有其他調(diào)用用于決定 instance 是非 null 的,并將其返回。多線程能夠安全并發(fā)地執(zhí)行除第一次調(diào)用外的所有調(diào)用。盡管如此,由于該方法是 synchronized 的,需要為該方法的每一次調(diào)用付出同步的代價(jià),即使只有第一次調(diào)用需要同步。

    為使此方法更為有效,一個(gè)被稱為雙重檢查鎖定的習(xí)語(yǔ)就應(yīng)運(yùn)而生了。這個(gè)想法是為了避免對(duì)除第一次調(diào)用外的所有調(diào)用都實(shí)行同步的昂貴代價(jià)。同步的代價(jià)在不同的 JVM 間是不同的。在早期,代價(jià)相當(dāng)高。隨著更高級(jí)的 JVM 的出現(xiàn),同步的代價(jià)降低了,但出入 synchronized 方法或塊仍然有性能損失。不考慮 JVM 技術(shù)的進(jìn)步,程序員們絕不想不必要地浪費(fèi)處理時(shí)間。

    因?yàn)橹挥星鍐?2 中的 //2 行需要同步,我們可以只將其包裝到一個(gè)同步塊中,如清單 3 所示:


    清單 3. getInstance() 方法
                            public static Singleton getInstance()
                {
                if (instance == null)
                {
                synchronized(Singleton.class) {
                instance = new Singleton();
                }
                }
                return instance;
                }
                

    清單 3 中的代碼展示了用多線程加以說(shuō)明的和清單 1 相同的問(wèn)題。當(dāng) instancenull 時(shí),兩個(gè)線程可以并發(fā)地進(jìn)入 if 語(yǔ)句內(nèi)部。然后,一個(gè)線程進(jìn)入 synchronized 塊來(lái)初始化 instance,而另一個(gè)線程則被阻斷。當(dāng)?shù)谝粋€(gè)線程退出 synchronized 塊時(shí),等待著的線程進(jìn)入并創(chuàng)建另一個(gè) Singleton 對(duì)象。注意:當(dāng)?shù)诙€(gè)線程進(jìn)入 synchronized 塊時(shí),它并沒(méi)有檢查 instance 是否非 null







    雙重檢查鎖定

    為處理清單 3 中的問(wèn)題,我們需要對(duì) instance 進(jìn)行第二次檢查。這就是“雙重檢查鎖定”名稱的由來(lái)。將雙重檢查鎖定習(xí)語(yǔ)應(yīng)用到清單 3 的結(jié)果就是清單 4 。


    清單 4. 雙重檢查鎖定示例
                            public static Singleton getInstance()
                {
                if (instance == null)
                {
                synchronized(Singleton.class) {  //1
                if (instance == null)          //2
                instance = new Singleton();  //3
                }
                }
                return instance;
                }
                

    雙重檢查鎖定背后的理論是:在 //2 處的第二次檢查使(如清單 3 中那樣)創(chuàng)建兩個(gè)不同的 Singleton 對(duì)象成為不可能。假設(shè)有下列事件序列:

    1. 線程 1 進(jìn)入 getInstance() 方法。

    2. 由于 instancenull,線程 1 在 //1 處進(jìn)入 synchronized 塊。

    3. 線程 1 被線程 2 預(yù)占。

    4. 線程 2 進(jìn)入 getInstance() 方法。

    5. 由于 instance 仍舊為 null,線程 2 試圖獲取 //1 處的鎖。然而,由于線程 1 持有該鎖,線程 2 在 //1 處阻塞。

    6. 線程 2 被線程 1 預(yù)占。

    7. 線程 1 執(zhí)行,由于在 //2 處實(shí)例仍舊為 null,線程 1 還創(chuàng)建一個(gè) Singleton 對(duì)象并將其引用賦值給 instance

    8. 線程 1 退出 synchronized 塊并從 getInstance() 方法返回實(shí)例。

    9. 線程 1 被線程 2 預(yù)占。

    10. 線程 2 獲取 //1 處的鎖并檢查 instance 是否為 null

    11. 由于 instance 是非 null 的,并沒(méi)有創(chuàng)建第二個(gè) Singleton 對(duì)象,由線程 1 創(chuàng)建的對(duì)象被返回。

    雙重檢查鎖定背后的理論是完美的。不幸地是,現(xiàn)實(shí)完全不同。雙重檢查鎖定的問(wèn)題是:并不能保證它會(huì)在單處理器或多處理器計(jì)算機(jī)上順利運(yùn)行。

    雙重檢查鎖定失敗的問(wèn)題并不歸咎于 JVM 中的實(shí)現(xiàn) bug,而是歸咎于 Java 平臺(tái)內(nèi)存模型。內(nèi)存模型允許所謂的“無(wú)序?qū)懭?#8221;,這也是這些習(xí)語(yǔ)失敗的一個(gè)主要原因。







    無(wú)序?qū)懭?/span>

    為解釋該問(wèn)題,需要重新考察上述清單 4 中的 //3 行。此行代碼創(chuàng)建了一個(gè) Singleton 對(duì)象并初始化變量 instance 來(lái)引用此對(duì)象。這行代碼的問(wèn)題是:在 Singleton 構(gòu)造函數(shù)體執(zhí)行之前,變量 instance 可能成為非 null 的。

    什么?這一說(shuō)法可能讓您始料未及,但事實(shí)確實(shí)如此。在解釋這個(gè)現(xiàn)象如何發(fā)生前,請(qǐng)先暫時(shí)接受這一事實(shí),我們先來(lái)考察一下雙重檢查鎖定是如何被破壞的。假設(shè)清單 4 中代碼執(zhí)行以下事件序列:

    1. 線程 1 進(jìn)入 getInstance() 方法。

    2. 由于 instancenull,線程 1 在 //1 處進(jìn)入 synchronized 塊。

    3. 線程 1 前進(jìn)到 //3 處,但在構(gòu)造函數(shù)執(zhí)行之前,使實(shí)例成為非 null

    4. 線程 1 被線程 2 預(yù)占。

    5. 線程 2 檢查實(shí)例是否為 null。因?yàn)閷?shí)例不為 null,線程 2 將 instance 引用返回給一個(gè)構(gòu)造完整但部分初始化了的 Singleton 對(duì)象。

    6. 線程 2 被線程 1 預(yù)占。

    7. 線程 1 通過(guò)運(yùn)行 Singleton 對(duì)象的構(gòu)造函數(shù)并將引用返回給它,來(lái)完成對(duì)該對(duì)象的初始化。

    此事件序列發(fā)生在線程 2 返回一個(gè)尚未執(zhí)行構(gòu)造函數(shù)的對(duì)象的時(shí)候。

    為展示此事件的發(fā)生情況,假設(shè)為代碼行 instance =new Singleton(); 執(zhí)行了下列偽代碼: instance =new Singleton();

    mem = allocate();             //Allocate memory for Singleton object.
                instance = mem;               //Note that instance is now non-null, but
                //has not been initialized.
                ctorSingleton(instance);      //Invoke constructor for Singleton passing
                //instance.
                

    這段偽代碼不僅是可能的,而且是一些 JIT 編譯器上真實(shí)發(fā)生的。執(zhí)行的順序是顛倒的,但鑒于當(dāng)前的內(nèi)存模型,這也是允許發(fā)生的。JIT 編譯器的這一行為使雙重檢查鎖定的問(wèn)題只不過(guò)是一次學(xué)術(shù)實(shí)踐而已。

    為說(shuō)明這一情況,假設(shè)有清單 5 中的代碼。它包含一個(gè)剝離版的 getInstance() 方法。我已經(jīng)刪除了“雙重檢查性”以簡(jiǎn)化我們對(duì)生成的匯編代碼(清單 6)的回顧。我們只關(guān)心 JIT 編譯器如何編譯 instance=new Singleton(); 代碼。此外,我提供了一個(gè)簡(jiǎn)單的構(gòu)造函數(shù)來(lái)明確說(shuō)明匯編代碼中該構(gòu)造函數(shù)的運(yùn)行情況。


    清單 5. 用于演示無(wú)序?qū)懭氲膯卫?/strong>
                            class Singleton
                {
                private static Singleton instance;
                private boolean inUse;
                private int val;
                private Singleton()
                {
                inUse = true;
                val = 5;
                }
                public static Singleton getInstance()
                {
                if (instance == null)
                instance = new Singleton();
                return instance;
                }
                }
                

    清單 6 包含由 Sun JDK 1.2.1 JIT 編譯器為清單 5 中的 getInstance() 方法體生成的匯編代碼。


    清單 6. 由清單 5 中的代碼生成的匯編代碼
                            ;asm code generated for getInstance
                054D20B0   mov         eax,[049388C8]      ;load instance ref
                054D20B5   test        eax,eax             ;test for null
                054D20B7   jne         054D20D7
                054D20B9   mov         eax,14C0988h
                054D20BE   call        503EF8F0            ;allocate memory
                054D20C3   mov         [049388C8],eax      ;store pointer in
                ;instance ref. instance
                ;non-null and ctor
                ;has not run
                054D20C8   mov         ecx,dword ptr [eax]
                054D20CA   mov         dword ptr [ecx],1   ;inline ctor - inUse=true;
                054D20D0   mov         dword ptr [ecx+4],5 ;inline ctor - val=5;
                054D20D7   mov         ebx,dword ptr ds:[49388C8h]
                054D20DD   jmp         054D20B0
                

    注: 為引用下列說(shuō)明中的匯編代碼行,我將引用指令地址的最后兩個(gè)值,因?yàn)樗鼈兌家?054D20 開(kāi)頭。例如,B5 代表 test eax,eax

    匯編代碼是通過(guò)運(yùn)行一個(gè)在無(wú)限循環(huán)中調(diào)用 getInstance() 方法的測(cè)試程序來(lái)生成的。程序運(yùn)行時(shí),請(qǐng)運(yùn)行 Microsoft Visual C++ 調(diào)試器并將其附到表示測(cè)試程序的 Java 進(jìn)程中。然后,中斷執(zhí)行并找到表示該無(wú)限循環(huán)的匯編代碼。

    B0B5 處的前兩行匯編代碼將 instance 引用從內(nèi)存位置 049388C8 加載至 eax 中,并進(jìn)行 null 檢查。這跟清單 5 中的 getInstance() 方法的第一行代碼相對(duì)應(yīng)。第一次調(diào)用此方法時(shí),instancenull,代碼執(zhí)行到 B9BE 處的代碼為 Singleton 對(duì)象從堆中分配內(nèi)存,并將一個(gè)指向該塊內(nèi)存的指針存儲(chǔ)到 eax 中。下一行代碼,C3,獲取 eax 中的指針并將其存儲(chǔ)回內(nèi)存位置為 049388C8 的實(shí)例引用。結(jié)果是,instance 現(xiàn)在為非 null 并引用一個(gè)有效的 Singleton 對(duì)象。然而,此對(duì)象的構(gòu)造函數(shù)尚未運(yùn)行,這恰是破壞雙重檢查鎖定的情況。然后,在 C8 行處,instance 指針被解除引用并存儲(chǔ)到 ecxCAD0 行表示內(nèi)聯(lián)的構(gòu)造函數(shù),該構(gòu)造函數(shù)將值 true5 存儲(chǔ)到 Singleton 對(duì)象。如果此代碼在執(zhí)行 C3 行后且在完成該構(gòu)造函數(shù)前被另一個(gè)線程中斷,則雙重檢查鎖定就會(huì)失敗。

    不是所有的 JIT 編譯器都生成如上代碼。一些生成了代碼,從而只在構(gòu)造函數(shù)執(zhí)行后使 instance 成為非 null。針對(duì) Java 技術(shù)的 IBM SDK 1.3 版和 Sun JDK 1.3 都生成這樣的代碼。然而,這并不意味著應(yīng)該在這些實(shí)例中使用雙重檢查鎖定。該習(xí)語(yǔ)失敗還有一些其他原因。此外,您并不總能知道代碼會(huì)在哪些 JVM 上運(yùn)行,而 JIT 編譯器總是會(huì)發(fā)生變化,從而生成破壞此習(xí)語(yǔ)的代碼。







    雙重檢查鎖定:獲取兩個(gè)

    考慮到當(dāng)前的雙重檢查鎖定不起作用,我加入了另一個(gè)版本的代碼,如清單 7 所示,從而防止您剛才看到的無(wú)序?qū)懭雴?wèn)題。


    清單 7. 解決無(wú)序?qū)懭雴?wèn)題的嘗試
                            public static Singleton getInstance()
                {
                if (instance == null)
                {
                synchronized(Singleton.class) {      //1
                Singleton inst = instance;         //2
                if (inst == null)
                {
                synchronized(Singleton.class) {  //3
                inst = new Singleton();        //4
                }
                instance = inst;                 //5
                }
                }
                }
                return instance;
                }
                

    看著清單 7 中的代碼,您應(yīng)該意識(shí)到事情變得有點(diǎn)荒謬。請(qǐng)記住,創(chuàng)建雙重檢查鎖定是為了避免對(duì)簡(jiǎn)單的三行 getInstance() 方法實(shí)現(xiàn)同步。清單 7 中的代碼變得難于控制。另外,該代碼沒(méi)有解決問(wèn)題。仔細(xì)檢查可獲悉原因。

    此代碼試圖避免無(wú)序?qū)懭雴?wèn)題。它試圖通過(guò)引入局部變量 inst 和第二個(gè) synchronized 塊來(lái)解決這一問(wèn)題。該理論實(shí)現(xiàn)如下:

    1. 線程 1 進(jìn)入 getInstance() 方法。

    2. 由于 instancenull,線程 1 在 //1 處進(jìn)入第一個(gè) synchronized 塊。

    3. 局部變量 inst 獲取 instance 的值,該值在 //2 處為 null

    4. 由于 instnull,線程 1 在 //3 處進(jìn)入第二個(gè) synchronized 塊。

    5. 線程 1 然后開(kāi)始執(zhí)行 //4 處的代碼,同時(shí)使 inst 為非 null,但在 Singleton 的構(gòu)造函數(shù)執(zhí)行前。(這就是我們剛才看到的無(wú)序?qū)懭雴?wèn)題。)

    6. 線程 1 被線程 2 預(yù)占。

    7. 線程 2 進(jìn)入 getInstance() 方法。

    8. 由于 instancenull,線程 2 試圖在 //1 處進(jìn)入第一個(gè) synchronized 塊。由于線程 1 目前持有此鎖,線程 2 被阻斷。

    9. 線程 1 然后完成 //4 處的執(zhí)行。

    10. 線程 1 然后將一個(gè)構(gòu)造完整的 Singleton 對(duì)象在 //5 處賦值給變量 instance,并退出這兩個(gè) synchronized 塊。

    11. 線程 1 返回 instance

    12. 然后執(zhí)行線程 2 并在 //2 處將 instance 賦值給 inst

    13. 線程 2 發(fā)現(xiàn) instance 為非 null,將其返回。

    這里的關(guān)鍵行是 //5。此行應(yīng)該確保 instance 只為 null 或引用一個(gè)構(gòu)造完整的 Singleton 對(duì)象。該問(wèn)題發(fā)生在理論和實(shí)際彼此背道而馳的情況下。

    由于當(dāng)前內(nèi)存模型的定義,清單 7 中的代碼無(wú)效。Java 語(yǔ)言規(guī)范(Java Language Specification,JLS)要求不能將 synchronized 塊中的代碼移出來(lái)。但是,并沒(méi)有說(shuō)不能將 synchronized 塊外面的代碼移 synchronized 塊中。

    JIT 編譯器會(huì)在這里看到一個(gè)優(yōu)化的機(jī)會(huì)。此優(yōu)化會(huì)刪除 //4 和 //5 處的代碼,組合并且生成清單 8 中所示的代碼。


    清單 8. 從清單 7 中優(yōu)化來(lái)的代碼。
                            public static Singleton getInstance()
                {
                if (instance == null)
                {
                synchronized(Singleton.class) {      //1
                Singleton inst = instance;         //2
                if (inst == null)
                {
                synchronized(Singleton.class) {  //3
                //inst = new Singleton();      //4
                instance = new Singleton();
                }
                //instance = inst;               //5
                }
                }
                }
                return instance;
                }
                

    如果進(jìn)行此項(xiàng)優(yōu)化,您將同樣遇到我們之前討論過(guò)的無(wú)序?qū)懭雴?wèn)題。







    用 volatile 聲明每一個(gè)變量怎么樣?

    另一個(gè)想法是針對(duì)變量 inst 以及 instance 使用關(guān)鍵字 volatile。根據(jù) JLS(參見(jiàn) 參考資料),聲明成 volatile 的變量被認(rèn)為是順序一致的,即,不是重新排序的。但是試圖使用 volatile 來(lái)修正雙重檢查鎖定的問(wèn)題,會(huì)產(chǎn)生以下兩個(gè)問(wèn)題:

    • 這里的問(wèn)題不是有關(guān)順序一致性的,而是代碼被移動(dòng)了,不是重新排序。

    • 即使考慮了順序一致性,大多數(shù)的 JVM 也沒(méi)有正確地實(shí)現(xiàn) volatile

    第二點(diǎn)值得展開(kāi)討論。假設(shè)有清單 9 中的代碼:


    清單 9. 使用了 volatile 的順序一致性
                            class test
                {
                private volatile boolean stop = false;
                private volatile int num = 0;
                public void foo()
                {
                num = 100;    //This can happen second
                stop = true;  //This can happen first
                //...
                }
                public void bar()
                {
                if (stop)
                num += num;  //num can == 0!
                }
                //...
                }
                

    根據(jù) JLS,由于 stopnum 被聲明為 volatile,它們應(yīng)該順序一致。這意味著如果 stop 曾經(jīng)是 truenum 一定曾被設(shè)置成 100。盡管如此,因?yàn)樵S多 JVM 沒(méi)有實(shí)現(xiàn) volatile 的順序一致性功能,您就不能依賴此行為。因此,如果線程 1 調(diào)用 foo 并且線程 2 并發(fā)地調(diào)用 bar,則線程 1 可能在 num 被設(shè)置成為 100 之前將 stop 設(shè)置成 true。這將導(dǎo)致線程見(jiàn)到 stoptrue,而 num 仍被設(shè)置成 0。使用 volatile 和 64 位變量的原子數(shù)還有另外一些問(wèn)題,但這已超出了本文的討論范圍。有關(guān)此主題的更多信息,請(qǐng)參閱 參考資料







    解決方案

    底線就是:無(wú)論以何種形式,都不應(yīng)使用雙重檢查鎖定,因?yàn)槟荒鼙WC它在任何 JVM 實(shí)現(xiàn)上都能順利運(yùn)行。JSR-133 是有關(guān)內(nèi)存模型尋址問(wèn)題的,盡管如此,新的內(nèi)存模型也不會(huì)支持雙重檢查鎖定。因此,您有兩種選擇:

    • 接受如清單 2 中所示的 getInstance() 方法的同步。

    • 放棄同步,而使用一個(gè) static 字段。

    選擇項(xiàng) 2 如清單 10 中所示


    清單 10. 使用 static 字段的單例實(shí)現(xiàn)
                            class Singleton
                {
                private Vector v;
                private boolean inUse;
                private static Singleton instance = new Singleton();
                private Singleton()
                {
                v = new Vector();
                inUse = true;
                //...
                }
                public static Singleton getInstance()
                {
                return instance;
                }
                }
                

    清單 10 的代碼沒(méi)有使用同步,并且確保調(diào)用 static getInstance() 方法時(shí)才創(chuàng)建 Singleton。如果您的目標(biāo)是消除同步,則這將是一個(gè)很好的選擇。







    String 不是不變的

    鑒于無(wú)序?qū)懭牒鸵迷跇?gòu)造函數(shù)執(zhí)行前變成非 null 的問(wèn)題,您可能會(huì)考慮 String 類。假設(shè)有下列代碼:

    private String str;
                //...
                str = new String("hello");
                

    String 類應(yīng)該是不變的。盡管如此,鑒于我們之前討論的無(wú)序?qū)懭雴?wèn)題,那會(huì)在這里導(dǎo)致問(wèn)題嗎?答案是肯定的。考慮兩個(gè)線程訪問(wèn) String str。一個(gè)線程能看見(jiàn) str 引用一個(gè) String 對(duì)象,在該對(duì)象中構(gòu)造函數(shù)尚未運(yùn)行。事實(shí)上,清單 11 包含展示這種情況發(fā)生的代碼。注意,這個(gè)代碼僅在我測(cè)試用的舊版 JVM 上會(huì)失敗。IBM 1.3 和 Sun 1.3 JVM 都會(huì)如期生成不變的 String


    清單 11. 可變 String 的例子
                            class StringCreator extends Thread
                {
                MutableString ms;
                public StringCreator(MutableString muts)
                {
                ms = muts;
                }
                public void run()
                {
                while(true)
                ms.str = new String("hello");          //1
                }
                }
                class StringReader extends Thread
                {
                MutableString ms;
                public StringReader(MutableString muts)
                {
                ms = muts;
                }
                public void run()
                {
                while(true)
                {
                if (!(ms.str.equals("hello")))         //2
                {
                System.out.println("String is not immutable!");
                break;
                }
                }
                }
                }
                class MutableString
                {
                public String str;                         //3
                public static void main(String args[])
                {
                MutableString ms = new MutableString();  //4
                new StringCreator(ms).start();           //5
                new StringReader(ms).start();            //6
                }
                }
                

    此代碼在 //4 處創(chuàng)建一個(gè) MutableString 類,它包含了一個(gè) String 引用,此引用由 //3 處的兩個(gè)線程共享。在行 //5 和 //6 處,在兩個(gè)分開(kāi)的線程上創(chuàng)建了兩個(gè)對(duì)象 StringCreatorStringReader。傳入一個(gè) MutableString 對(duì)象的引用。StringCreator 類進(jìn)入到一個(gè)無(wú)限循環(huán)中并且使用值“hello”在 //1 處創(chuàng)建 String 對(duì)象。StringReader 也進(jìn)入到一個(gè)無(wú)限循環(huán)中,并且在 //2 處檢查當(dāng)前的 String 對(duì)象的值是不是 “hello”。如果不行,StringReader 線程打印出一條消息并停止。如果 String 類是不變的,則從此程序應(yīng)當(dāng)看不到任何輸出。如果發(fā)生了無(wú)序?qū)懭雴?wèn)題,則使 StringReader 看到 str 引用的惟一方法絕不是值為“hello”的 String 對(duì)象。

    在舊版的 JVM 如 Sun JDK 1.2.1 上運(yùn)行此代碼會(huì)導(dǎo)致無(wú)序?qū)懭雴?wèn)題。并因此導(dǎo)致一個(gè)非不變的 String







    結(jié)束語(yǔ)

    為避免單例中代價(jià)高昂的同步,程序員非常聰明地發(fā)明了雙重檢查鎖定習(xí)語(yǔ)。不幸的是,鑒于當(dāng)前的內(nèi)存模型的原因,該習(xí)語(yǔ)尚未得到廣泛使用,就明顯成為了一種不安全的編程結(jié)構(gòu)。重定義脆弱的內(nèi)存模型這一領(lǐng)域的工作正在進(jìn)行中。盡管如此,即使是在新提議的內(nèi)存模型中,雙重檢查鎖定也是無(wú)效的。對(duì)此問(wèn)題最佳的解決方案是接受同步或者使用一個(gè) static field

    posted @ 2011-05-08 19:17 胡鵬 閱讀(344) | 評(píng)論 (0)編輯 收藏
    薪水族如何“錢滾錢” 教你用2萬(wàn)賺到1000萬(wàn)
    工薪族月薪2000元的理財(cái)竅門(mén)
    在有很多的大學(xué)生都是在畢業(yè)以后選擇留在自己上學(xué)的城市,一來(lái)對(duì)城市有了感情,二來(lái)也希望能在大的城市有所發(fā)展,而現(xiàn)在很多大城市勞動(dòng)力過(guò)剩,大學(xué)生想找到一個(gè)自己喜歡又有較高收入的職位已經(jīng)變得非常難,很多剛畢業(yè)的朋友的月收入都可能徘徊在2000元人民幣左右,如果您是這樣的情況,讓我們來(lái)核算一下,如何利用手中的有限資金來(lái)進(jìn)行理財(cái)。如果您是單身一人,月收入在2000人民幣,又沒(méi)有其他的獎(jiǎng)金分紅等收入,那年收入就固定在25000元左右。如何來(lái)支配這些錢呢?
    生活費(fèi)占收入30%-40%
    首先,你要拿出每個(gè)月必須支付的生活費(fèi)。如房租、水電、通訊費(fèi)、柴米油鹽等,這部分約占收入三分之一。它們是你生活中不可或缺的部分,滿足你最基本的物質(zhì)需求。離開(kāi)了它們,你就會(huì)像魚(yú)兒離開(kāi)了水一樣無(wú)法生活,所以無(wú)論如何,請(qǐng)你先從收入中抽出這部分,不要?jiǎng)佑谩?br /> 儲(chǔ)蓄占收入10%-20%
    其次,是自己用來(lái)儲(chǔ)蓄的部分,約占收入的10%-20%。很多人每次也都會(huì)在月初存錢,但是到了月底的時(shí)候,往往就變成了泡沫,存進(jìn)去的大部分又取出來(lái)了,而且是不知不覺(jué)的,好像憑空消失了一樣,總是在自己喜歡的衣飾、雜志、CD或朋友聚會(huì)上不加以節(jié)制。你要自己提醒自己,起碼,你的存儲(chǔ)能保證你3個(gè)月的基本生活。要知道,現(xiàn)在很多公司動(dòng)輒減薪裁員。如果你一點(diǎn)儲(chǔ)蓄都沒(méi)有,一旦工作發(fā)生了變動(dòng),你將會(huì)非常被動(dòng)。
    而且這3個(gè)月的收入可以成為你的定心丸,工作實(shí)在干得不開(kāi)心了,忍無(wú)可忍無(wú)需再忍時(shí),你可以瀟灑地對(duì)老板說(shuō)聲“拜拜”。想想可以不用受你不喜歡的工作和人的氣,是多么開(kāi)心的事啊。所以,無(wú)論如何,請(qǐng)為自己留條退路。
    活動(dòng)資金占收入30%~40%
    剩下的這部分錢,約占收入的三分之一。可以根據(jù)自己當(dāng)時(shí)的生活目標(biāo),側(cè)重地花在不同的地方。譬如“五一”、“十一”可以安排旅游;服裝打折時(shí)可以購(gòu)進(jìn)自己心儀已久的牌子貨;還有平時(shí)必不可少的購(gòu)買CD、朋友聚會(huì)的開(kāi)銷。這樣花起來(lái)心里有數(shù),不會(huì)一下子把錢都用完。
    最關(guān)鍵的是,即使一發(fā)薪水就把這部分用完了,也可當(dāng)是一次教訓(xùn),可以懲罰自己一個(gè)月內(nèi)什么都不能再干了(就當(dāng)是收入全部支出了吧),印象會(huì)很深刻而且有效。
    除去吃、穿、住、行以及其他的消費(fèi)外,再怎么節(jié)省,估計(jì)您現(xiàn)在的狀況,一年也只有10000元的積蓄,想來(lái)這些都是剛畢業(yè)的絕大部分學(xué)生所面臨的實(shí)際情況。如何讓錢生錢是大家想得最多的事情,然而,畢竟收入有限,很多想法都不容易實(shí)現(xiàn),建議處于這個(gè)階段的朋友,最重要的是開(kāi)源,節(jié)流只是我們生活工作的一部分,就像大廈的基層一樣。而最重要的是怎樣財(cái)源滾滾、開(kāi)源有道,為了達(dá)到一個(gè)新目標(biāo),你必須不斷進(jìn)步以求發(fā)展,培養(yǎng)自己的實(shí)力以求進(jìn)步,這才是真正的生財(cái)之道。可以安心地發(fā)展自己的事業(yè),積累自己的經(jīng)驗(yàn),充實(shí)自己,使自己不斷地提高,才會(huì)有好的發(fā)展,要相信“機(jī)會(huì)總是給有準(zhǔn)備的人”。
    當(dāng)然,既然有了些許積蓄,也不能讓它閑置,我們建議把1萬(wàn)元分為5份,分成5個(gè)2000元,分別作出適當(dāng)?shù)耐顿Y安排。這樣,家庭不會(huì)出現(xiàn)用錢危機(jī),并可以獲得最大的收益。
    (1)用2000元買國(guó)債,這是回報(bào)率較高而又很保險(xiǎn)的一種投資。
    (2)用2000元買保險(xiǎn)。以往人們的保險(xiǎn)意識(shí)很淡薄,實(shí)際上購(gòu)買保險(xiǎn)也是一種較好的投資方式,而且保險(xiǎn)金不在利息稅征收之列。尤其是各壽險(xiǎn)公司都推出了兩全型險(xiǎn)種,增加了有關(guān)“權(quán)益轉(zhuǎn)換”的條款,即一旦銀行利率上升,客戶可在保險(xiǎn)公司出售的險(xiǎn)種中進(jìn)行轉(zhuǎn)換,并獲得保險(xiǎn)公司給予的一定的價(jià)格折扣、免予核保等優(yōu)惠政策。
    (3)用2000元買股票。這是一種風(fēng)險(xiǎn)最大的投資,當(dāng)然風(fēng)險(xiǎn)與收益是并存的,只要選擇得當(dāng),會(huì)帶來(lái)理想的投資回報(bào)。除股票外,期貨、投資債券等都屬這一類。不過(guò),參與這類投資,要求有相應(yīng)的行業(yè)知識(shí)和較強(qiáng)的風(fēng)險(xiǎn)意識(shí)。
    (4)用2000元存定期存款,這是一種幾乎沒(méi)有風(fēng)險(xiǎn)的投資方式,也是未來(lái)對(duì)家庭生活的一種保障。
    (5)用2000元存活期存款,這是為了應(yīng)急之用。如家里臨時(shí)急需用錢,有一定數(shù)量的活期儲(chǔ)蓄存款可解燃眉之急,而且存取又很方便。
    這種方法是許多人經(jīng)過(guò)多年嘗試后總結(jié)出的一套成功的理財(cái)經(jīng)驗(yàn)。當(dāng)然,各個(gè)家庭可以根據(jù)不同情況,靈活使用。
    正確理財(cái)三個(gè)觀念
    建立理財(cái)觀念一:理財(cái)是一件正大光明的事,“你不理財(cái),財(cái)不理你”。
    建立理財(cái)觀念二:理財(cái)要從現(xiàn)在開(kāi)始,并長(zhǎng)期堅(jiān)持。
    建立理財(cái)觀念三:理財(cái)目的是“梳理財(cái)富,增值生活”。
    理財(cái)四個(gè)誤區(qū)
    理財(cái)觀念誤區(qū)一:我沒(méi)財(cái)可理;
    理財(cái)觀念誤區(qū)二:我不需要理財(cái);
    理財(cái)觀念誤區(qū)三:等我有了錢再理財(cái);
    理財(cái)觀念誤區(qū)四:會(huì)理財(cái)不如會(huì)掙錢。
    理財(cái)?shù)奈宕竽繕?biāo)
    目標(biāo)一:獲得資產(chǎn)增值;
    目標(biāo)二:保證資金安全;
    目標(biāo)三:防御意外事故;
    目標(biāo)四:保證老有所養(yǎng);
    目標(biāo)五:提供贍養(yǎng)父母及撫養(yǎng)教育子女的基金。
    --------------------精彩閱讀推薦--------------------
    【500強(qiáng)企業(yè)的薪水有多高?】
    全球500強(qiáng)大企業(yè)的薪水實(shí)情大揭密
    不一定要是自己的offer letter上的數(shù)據(jù),凡是能夠確認(rèn)比較準(zhǔn)確的公司薪水都可補(bǔ)充。補(bǔ)充的話最好說(shuō)明職位、本碩區(qū)別、多少個(gè)月工資、獎(jiǎng)金。寶潔:本7200、研8200、博9700,均14個(gè)月,另有交通補(bǔ)助,區(qū)域補(bǔ)助等,CBD,marketing每幾個(gè)月漲20%-30%不定。
    【工薪族的你跑贏通脹了嗎?】
    工薪族理財(cái)跑贏通脹 開(kāi)源節(jié)流資產(chǎn)合理配備
    龍先生家是典型的工薪階層。龍先生47歲,是某大型企業(yè)的技術(shù)師,年收入5.5萬(wàn)元,購(gòu)買了各類基本保險(xiǎn)。太太42歲,是某商場(chǎng)的合同工,年收入4萬(wàn)元,購(gòu)買了基本的社會(huì)保險(xiǎn)。兩人均在單位吃中午飯,搭班車上下班。兒子16歲,尚在讀高中。
    【怎樣才能錢生錢?】
    “階梯存儲(chǔ)”應(yīng)對(duì)利率調(diào)整 學(xué)三招輕松錢生錢
    當(dāng)前,儲(chǔ)蓄依然在居民理財(cái)?shù)耐顿Y組合中占據(jù)著重要地位,但在當(dāng)前的加息周期內(nèi),一些人因缺乏科學(xué)的儲(chǔ)蓄理財(cái)規(guī)劃而損失利息收入。理財(cái)專家建議,進(jìn)入加息周期,為了使儲(chǔ)蓄理財(cái)能賺取更多的利息收入,儲(chǔ)戶應(yīng)在存款期限、存款金額和存款方式上注意以下幾點(diǎn)。
    【爺們的臉往哪擱!】
    女人太會(huì)賺錢也是錯(cuò)? 爺們兒的臉往哪擱
    女人財(cái)大就氣粗?別偏激,妻子賺錢自己也是受益者,所以首先心態(tài)放平和些,別太執(zhí)著于傳統(tǒng)的思維和他人的看法。會(huì)不會(huì)賺錢是女人衡量男人的重要標(biāo)尺。男人沒(méi)錢,女人覺(jué)得沒(méi)有面子,不愿提及她的男人;有錢男人不怕提及他女人,無(wú)論漂亮與否,只要不給他戴綠帽子。
    posted @ 2011-03-10 20:07 胡鵬 閱讀(153) | 評(píng)論 (0)編輯 收藏
           

            說(shuō)起精致,最容易想起的詞大概是瓷器了,但這個(gè)詞用到程序員身上,肯定讓很多人覺(jué)得摸不著頭腦,在詳述"精致"這個(gè)詞以前,還是先來(lái)看一個(gè)"破窗理論",讓我們真正的理解"精致"的概念。

           最早的"破窗理論",也稱"破窗謬論",源自于一位經(jīng)濟(jì)學(xué)家黑茲利特(也有人說(shuō)源于法國(guó)19世紀(jì)經(jīng)濟(jì)學(xué)家巴斯夏),用來(lái)指出"破壞創(chuàng)造財(cái)富"的概念,以徹底地否定凱恩斯主義的政府干預(yù)政策。但后來(lái)美國(guó)斯坦福大學(xué)心理學(xué)家詹巴斗和犯罪學(xué)家凱琳也提出了相應(yīng)的"破窗理論"。

            心理學(xué)家詹巴斗進(jìn)行了一項(xiàng)試驗(yàn),他把兩輛一模一樣的汽車分別停放在帕羅阿爾托的中產(chǎn)階級(jí)社區(qū)和相對(duì)雜亂的布朗克斯街區(qū)。對(duì)停在布朗克斯街區(qū)的那一輛,他摘掉了車牌,并且把頂棚打開(kāi),結(jié)果不到一天就被人偷走了;而停放在帕羅阿爾托的那一輛,停了一個(gè)星期也無(wú)人問(wèn)津。后來(lái),詹巴斗用錘子把這輛車的玻璃敲了個(gè)大洞,結(jié)果僅僅過(guò)了幾個(gè)小時(shí)車就不見(jiàn)了。

           而犯罪學(xué)家凱琳曾注意到一個(gè)問(wèn)題:在她上班的路旁,有一座非常漂亮的大樓,有一天,她注意到樓上有一窗子的玻璃被打破了,那扇破窗與整座大樓的整潔美麗極不調(diào)諧,顯得格外的刺眼。又過(guò)了一段時(shí)間,她驚奇地發(fā)現(xiàn):那扇破窗不但沒(méi)得到及時(shí)的維修,反而又增加了幾個(gè)帶爛玻璃的窗子……這一發(fā)現(xiàn)使她的心中忽有所悟:如果有人打壞了一個(gè)建筑物的窗戶玻璃,而這扇窗戶又得不到及時(shí)維修的話,別人就可能受到某些暗示性的縱容去打爛更多的玻璃。久而久之,這些破窗戶就給人造成一種無(wú)序的感覺(jué);其結(jié)果是:在這種麻木不仁的氛圍中,犯罪就會(huì)滋生。這就是凱琳著名的"破窗理論"。

            后來(lái)的"破窗理論",已經(jīng)突破原有經(jīng)濟(jì)學(xué)上的概念,有了新的意義:殘缺不全的東西更容易遭受到別人的破壞。前面的汽車和窗戶都表明了這一點(diǎn)。

           其實(shí)作為程序員開(kāi)發(fā)軟件也是一樣,可能有十種好的方法去寫(xiě)一個(gè)功能,一個(gè)類,但同時(shí)可能會(huì)有一百種更快捷但不好的方法去做同樣的事情,很多程序員會(huì)因?yàn)楦鞣N原因,如時(shí)間壓力,工作強(qiáng)度,技術(shù)水平等一系列問(wèn)題選擇了后者而非前者。同樣的事情還發(fā)生在維護(hù)和修改階段,當(dāng)看到別人的代碼寫(xiě)的隨意,不好時(shí),那么自然就會(huì)沿著別人的方向走下去,結(jié)果就是產(chǎn)生出更多不好的代碼,這是在代碼開(kāi)發(fā)中的一個(gè)典型"破窗理論"的體現(xiàn)。

       承認(rèn)一點(diǎn),現(xiàn)實(shí)世界是不完美,特別是開(kāi)發(fā)中,因?yàn)闀r(shí)間,精力,能力等各種因素,我們始終是要打破一些窗戶,但是卻要記住兩點(diǎn):
            1.一個(gè)月前多打破了一扇窗戶,結(jié)果一個(gè)月就會(huì)打破10 扇甚至更多的窗戶。
            2.如果打破了一扇窗戶,就要記住,遲早應(yīng)該將它補(bǔ)上。

            因?yàn)楦鞣矫娴脑颍粋€(gè)程序員也許不能做到精致的代碼,但是如果一個(gè)程序員不想去做精致的代碼,那么又何必選擇軟件開(kāi)發(fā)呢?
    posted @ 2011-01-11 22:35 胡鵬 閱讀(189) | 評(píng)論 (0)編輯 收藏
     

    最近有Java解壓縮的需求,java.util.zip實(shí)在不好用,對(duì)中文支持也不行。所以選擇了強(qiáng)大的TrueZIP,使用時(shí)遇到了一個(gè)問(wèn)題,做個(gè)記錄。
    解壓縮代碼如下:

    ArchiveDetector detector = new DefaultArchiveDetector(ArchiveDetector.ALL,
            new Object[] { "zip", new CheckedZip32Driver("GBK") } );
    File zipFile = new File("zipFile", detector);
    File dst = new File("dst");
    // 解壓縮
    zipFile.copyAllTo(dst);

    代碼十分簡(jiǎn)潔,注意這個(gè)File是

    de.schlichtherle.io.File

    不是

    java.io.File

    當(dāng)處理完業(yè)務(wù)要?jiǎng)h除這個(gè)Zip File時(shí),問(wèn)題出現(xiàn)了:
    這個(gè)文件刪不掉!!!
    把自己的代碼檢查了好久,確認(rèn)沒(méi)問(wèn)題后,開(kāi)始從TrueZIP下手,發(fā)現(xiàn)它有特殊的地方的,是提示過(guò)的:

    File file = new File(“archive.zip”); // de.schlichtherle.io.File!
    Please do not do this instead:
    de.schlichtherle.io.File file = new de.schlichtherle.io.File(“archive.zip”);


    This is for the following reasons:
    1.Accidentally using java.io.File and de.schlichtherle.io.File instances referring to the same path concurrently will result in erroneous behaviour and may even cause loss of data! Please refer to the section “Third Party Access” in the package Javadoc of de.schlichtherle.io for for full details and workarounds.
    2.A de.schlichtherle.io.File subclasses java.io.File and thanks to polymorphism can be used everywhere a java.io.File could be used.

    原來(lái)兩個(gè)File不能交叉使用,搞清楚原因了,加這么一句代碼搞定。

    zipFile.deleteAll();

    posted @ 2011-01-11 22:30 胡鵬 閱讀(1294) | 評(píng)論 (0)編輯 收藏
    http://www.tkk7.com/Files/lsbwahaha/ANTLR_info.pdf
    antlr簡(jiǎn)介


    目前的ANTLR支持的語(yǔ)法層的選項(xiàng)主要包括:

    語(yǔ)言選項(xiàng)(Language)、

    輸出選項(xiàng)(output)、

    回溯選項(xiàng)(backtrack)、

    記憶選項(xiàng) memorize)、

    記號(hào)詞庫(kù)(tokenVocab)、

    重寫(xiě)選項(xiàng)(rewrite)、

    超類選項(xiàng)(superClass)、

    過(guò)濾選項(xiàng)(Filter)、

    AST標(biāo)簽類型(ASTLabelType

    K選項(xiàng)

     

     

    /**
            //一些寫(xiě)法







    k=2;

            backtrack=true;

            memoize=true;

    */

     

    1.   語(yǔ)言選項(xiàng) language

     

    語(yǔ)言選項(xiàng)指定了ANTLR將要產(chǎn)生的代碼的目標(biāo)語(yǔ)言,默認(rèn)情況下該選項(xiàng)設(shè)置為了Java。需要注意的是,ANTLR中的嵌入的動(dòng)作必須要使用目標(biāo)語(yǔ)言來(lái)寫(xiě)。

    grammar T;
    options {
        language=Java;
    }

     

    ANTLR使用了特有的基于字串模板(StringTemplate-based)代碼生成器,構(gòu)建一個(gè)新的目標(biāo)語(yǔ)言顯得較為簡(jiǎn)單,因此我們可以構(gòu)建多種 語(yǔ)言,諸如JavaCC++C#PythonObjective-CRuby等等。語(yǔ)言選項(xiàng)讓ANNTLR去模板目錄(例如 org/antlr/codegen/templates/Java or org/antlr/codegen/templates/C)下尋找合適的模板,并使用模板來(lái)構(gòu)建語(yǔ)言。該目錄下包含大量的模板,我們可以向其中加入其 他的模板以滿足我們的需求。

    2.   輸出選項(xiàng) output

    輸出選項(xiàng)控制了ANTLR輸出的數(shù)據(jù)結(jié)構(gòu),目前支持兩種輸出:抽象語(yǔ)法樹(shù)——ASTAbstract Syntax Trees)和字串模板(StringTemplates——template。當(dāng)output這個(gè)選項(xiàng)被設(shè)置后,所有的規(guī)則都被輸出成了AST或者 template

    grammar T;
    options {
        output=AST;
    }

     

    3.   回溯選項(xiàng)backtrack

    當(dāng)回溯選項(xiàng)打開(kāi)的時(shí)候,在執(zhí)行一個(gè)LL(K)失敗的時(shí)候,ANTLR會(huì)返回至LL(K)開(kāi)始而嘗試其他的規(guī)則。

     

    4.   記憶選項(xiàng) memorize

    memoize選項(xiàng)打開(kāi)以后,每條解析方法(Paser Method)開(kāi)始之前,ANTLR會(huì)首先檢測(cè)以前的嘗試結(jié)果,并在該方法執(zhí)行完成之后記錄該規(guī)則是否執(zhí)行成功。但是注意,對(duì)于單條的規(guī)則打開(kāi)此選項(xiàng)經(jīng)常比在全局上打開(kāi)該規(guī)則效率更高。

     

    5.   記號(hào)詞庫(kù)(tokenVocab

    說(shuō)白了就是output輸出目錄中的XX.tokens文件中的定義可以方便的給 大型工程中多個(gè).g中的符號(hào)同步更新。

     

    大型的工程中常常利用AST作為中間產(chǎn)物對(duì)輸入進(jìn)行多次分析并最終生成代碼。對(duì)AST的遍歷時(shí)需要經(jīng)常使用樹(shù)語(yǔ)法(tree grammar),而tree grammar中經(jīng)常需要將符號(hào)與其他的文件中的符號(hào)進(jìn)行同步或者更新。tokenVocab實(shí)現(xiàn)了這個(gè)功能。
    例如我們定義了下面的一個(gè)語(yǔ)法文件:

    grammar P;
    options {
        output=AST;
    }
    expr: INT ('+' ^ INT)* ;
    INT : '0'..'9' +;
    WS : ' ' | '\r' | '\n' ;
    利用該文件生成了一個(gè)標(biāo)記:P.token,并生成了語(yǔ)法樹(shù)(AST)。這時(shí)我們需要一個(gè)用于遍歷該ASTtree grammar,并通過(guò)tree grammar 中的tokenVocab選項(xiàng)來(lái)向其中更新tokens:

    tree grammar Dump;
    options {
        tokenVocab=P;
        ASTLabelType=CommonTree;
    }
    expr: ^( '+' expr {System.out.print('+' );} expr )
        | INT {System.out.print($INT.text);}
        ;

    編譯tree grammar的時(shí)候ANTLR默認(rèn)會(huì)在當(dāng)前目錄下尋找.token文件,我們可以通過(guò)-lib選項(xiàng)來(lái)設(shè)置用于尋找.token文件的目錄,例如:
    java org.antlr.Tool -lib . Dump.g

    6.   重寫(xiě)選項(xiàng)(rewrite

    通過(guò)重寫(xiě)選項(xiàng)可以改變ANTLR對(duì)輸入的默認(rèn)處理規(guī)則,一般用在輸出為template的情況下。將該選項(xiàng)使能之后,ANTLR將一般的輸入直接拷貝至輸出,而將適于模板重寫(xiě)規(guī)則的輸入做其他的處理。

    7.   超類選項(xiàng)(superClass

    用于指定一個(gè)超類。

    8.   過(guò)濾選項(xiàng)(Filter

    9.   AST標(biāo)簽類型(ASTLabelType

    10.             K選項(xiàng)

       K選項(xiàng)用于限制對(duì)LL(K)進(jìn)行語(yǔ)法分析的次數(shù),從而提高了ANTLR的解析速度。K只能為*或者數(shù)字,默認(rèn)為*

     

     

     

     

    屬性和動(dòng)作

    動(dòng)作(Actions)實(shí)際上是用目標(biāo)語(yǔ)言寫(xiě)成的、嵌入到規(guī)則中的代碼(以花括號(hào)包裹)。它們通常直接操作輸入的標(biāo)號(hào),但是他們也可以用來(lái)調(diào)用相應(yīng)的外部代碼。屬性,到目前為止我的理解還不多,感覺(jué)像是C++中類里面的成員,一會(huì)看完應(yīng)該會(huì)更清楚一些。

    1.
    語(yǔ)法動(dòng)作(Grammar Actions
    動(dòng)作(Actions)是指嵌在語(yǔ)法中的、用目標(biāo)語(yǔ)言寫(xiě)成的代碼片段。ANTLR則把這些代碼(除了用$%標(biāo)記的以外)逐字地插入到生成的識(shí)別器中。
    動(dòng)作可以放到規(guī)則的外邊,也可以嵌入到某條規(guī)則當(dāng)中。當(dāng)動(dòng)作位于規(guī)則之外時(shí)候,這些動(dòng)作同城定義了一些全局的或者是類的成員(變量或者成員函數(shù));而當(dāng)其嵌入規(guī)則之中時(shí),則用于執(zhí)行某些特定的命令,這些命令在識(shí)別器識(shí)別了其預(yù)訂的字符的時(shí)候就會(huì)開(kāi)始執(zhí)行。例如下面的例子:

    parser grammar T;
    @header {
        package p;
    }
    @members {
        int i;
        public TParser(TokenStream input, int foo) {
            this(input);
            i = foo;
        }
    }
    a[int x] returns [int y]
    @init {int z=0;}
    @after {System.out.println("after matching rule; before finally");}
    : {
    action1} A {action2 }
    ;
    catch[RecognitionException re] {
        System.err.println("error");
    }
    finally {
    do-this-no-matter-what }

    從中可以看出,前面的兩個(gè)動(dòng)作,@head and @members是兩個(gè)處于規(guī)則之外的全局的動(dòng)作,定義了一些變量和類;而后兩個(gè)則分別在a這個(gè)規(guī)則的前后執(zhí)行(@init在前,@after在后,這個(gè)在前面提到過(guò))。 這里針對(duì)兩種類型詳細(xì)敘述。


    antlr簡(jiǎn)介
    posted @ 2010-12-17 19:20 胡鵬 閱讀(1510) | 評(píng)論 (0)編輯 收藏

    導(dǎo)航

    <2010年12月>
    2829301234
    567891011
    12131415161718
    19202122232425
    2627282930311
    2345678

    統(tǒng)計(jì)

    • 隨筆 - 93
    • 文章 - 0
    • 評(píng)論 - 48
    • 引用 - 0

    常用鏈接

    留言簿(3)

    隨筆分類

    隨筆檔案

    agile

    搜索

    •  

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 亚洲高清偷拍一区二区三区| 亚洲色大18成人网站WWW在线播放| 成人免费夜片在线观看| 麻豆精品国产免费观看| 亚洲国产最大av| 亚洲免费福利视频| 亚洲天堂一区二区| 久久国产精品免费视频| 亚洲精品你懂的在线观看| eeuss影院ss奇兵免费com| 全部免费国产潢色一级| 老司机亚洲精品影院在线观看| 成人超污免费网站在线看| 在线亚洲午夜片AV大片| 我们的2018在线观看免费高清| 久久亚洲精品无码VA大香大香| 亚洲精品免费观看| 亚洲伊人tv综合网色| 久久亚洲免费视频| 亚洲av日韩av天堂影片精品| 182tv免费视频在线观看| 亚洲精品V欧洲精品V日韩精品| 两个人www免费高清视频| 国产AⅤ无码专区亚洲AV| 一级做a免费视频观看网站| 亚洲欧洲日本在线| jizz免费在线影视观看网站| 中文字幕在亚洲第一在线| 国产精品成人69XXX免费视频| 久久久青草青青国产亚洲免观| 一级毛片在线免费视频| 国产亚洲色视频在线| 91免费福利视频| 久久精品国产亚洲香蕉| 95老司机免费福利| 亚洲永久中文字幕在线| 国产啪精品视频网免费| 亚洲七久久之综合七久久| 国产传媒在线观看视频免费观看| 边摸边脱吃奶边高潮视频免费| 亚洲狠狠爱综合影院婷婷|