Fantasy's World

          世界的小世界,我的大世界^_^

            BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
            6 Posts :: 0 Stories :: 16 Comments :: 0 Trackbacks

          2005年10月6日 #

          首先看看我寫的一個小程序:

          public class TestTry extends Exception
          {
           static boolean f=false;
           static int sum=0;
           static int created=0;
           static int i=0;
           TestTry()
           {
            i=created++;
            if(created>=299) f=true;
            }
           public void finalize()
           {
            sum++;
            }
           public static void main(String[] args)
           {
            while(!TestTry.f)
            {
             try{
              throw new TestTry();
              }catch(Exception e){}
              finally{
               System.out.println("Creat "+TestTry.i+" TestTry, "+TestTry.sum+" has been finalized!");
               }
              }
            //System.out.println("Creat "+TestTry.created+" TestTry, "+TestTry.sum+" has been finalized!"); 
            }
           }

          這個是我在測試在try語句拋出異常后,在try語句中建立的對象是否會調(diào)用自身的終止函數(shù)時(shí)發(fā)現(xiàn)的,這里有個奇怪的現(xiàn)象在if(created>=299) f=true;這條語句中,如果把條件created>=299改為>=比299更大的數(shù),你會發(fā)現(xiàn)System.out.println("Creat "+TestTry.i+" TestTry, "+TestTry.sum+" has been finalized!");這條語句的輸出的結(jié)果并不是你預(yù)想的那樣(輸出判斷的數(shù)字+1的行數(shù)),而只是顯示最后的三百行。那么在這之前拋出的異常上哪里去了呢?難道說Java只處理最后拋出的三百的異常么?
          posted @ 2005-12-29 18:21 FinalFantasy 閱讀(367) | 評論 (0)編輯 收藏

          這個文檔是老師給我們看的,看了之后收獲不少,帖出來讓大家也看看:)

          引言

          Java的堆是一個運(yùn)行時(shí)數(shù)據(jù)區(qū),類的實(shí)例(對象)從中分配空間。Java虛擬機(jī)(JVM)的堆中儲存著正在運(yùn)行的應(yīng)用程序所建立的所有對象,這些對象通過newnewarrayanewarraymultianewarray等指令建立,但是它們不需要程序代碼來顯式地釋放。一般來說,堆的是由垃圾回收 來負(fù)責(zé)的,盡管JVM規(guī)范并不要求特殊的垃圾回收技術(shù),甚至根本就不需要垃圾回收,但是由于內(nèi)存的有限性,JVM在實(shí)現(xiàn)的時(shí)候都有一個由垃圾回收所管理的堆。垃圾回收是一種動態(tài)存儲管理技術(shù),它自動地釋放不再被程序引用的對象,按照特定的垃圾收集算法來實(shí)現(xiàn)資源自動回收的功能。

          垃圾收集的意義

          C++中,對象所占的內(nèi)存在程序結(jié)束運(yùn)行之前一直被占用,在明確釋放之前不能分配給其它對象;而在Java中,當(dāng)沒有對象引用指向原先分配給某個對象的內(nèi)存時(shí),該內(nèi)存便成為垃圾。JVM的一個系統(tǒng)級線程會自動釋放該內(nèi)存塊。垃圾收集意味著程序不再需要的對象是"無用信息",這些信息將被丟棄。當(dāng)一個對象不再被引用的時(shí)候,內(nèi)存回收它占領(lǐng)的空間,以便空間被后來的新對象使用。事實(shí)上,除了釋放沒用的對象,垃圾收集也可以清除內(nèi)存記錄碎片。由于創(chuàng)建對象和垃圾收集器釋放丟棄對象所占的內(nèi)存空間,內(nèi)存會出現(xiàn)碎片。碎片是分配給對象的內(nèi)存塊之間的空閑內(nèi)存洞。碎片整理將所占用的堆內(nèi)存移到堆的一端,JVM將整理出的內(nèi)存分配給新的對象。

          垃圾收集能自動釋放內(nèi)存空間,減輕編程的負(fù)擔(dān)。這使Java 虛擬機(jī)具有一些優(yōu)點(diǎn)。首先,它能使編程效率提高。在沒有垃圾收集機(jī)制的時(shí)候,可能要花許多時(shí)間來解決一個難懂的存儲器問題。在用Java語言編程的時(shí)候,靠垃圾收集機(jī)制可大大縮短時(shí)間。其次是它保護(hù)程序的完整性, 垃圾收集是Java語言安全性策略的一個重要部份。

          垃圾收集的一個潛在的缺點(diǎn)是它的開銷影響程序性能。Java虛擬機(jī)必須追蹤運(yùn)行程序中有用的對象, 而且最終釋放沒用的對象。這一個過程需要花費(fèi)處理器的時(shí)間。其次垃圾收集算法的不完備性,早先采用的某些垃圾收集算法就不能保證100%收集到所有的廢棄內(nèi)存。當(dāng)然隨著垃圾收集算法的不斷改進(jìn)以及軟硬件運(yùn)行效率的不斷提升,這些問題都可以迎刃而解。

          垃圾收集的算法分析

          Java語言規(guī)范沒有明確地說明JVM使用哪種垃圾回收算法,但是任何一種垃圾收集算法一般要做2件基本的事情:(1)發(fā)現(xiàn)無用信息對象;(2)回收被無用對象占用的內(nèi)存空間,使該空間可被程序再次使用。

          大多數(shù)垃圾回收算法使用了根集(root set)這個概念;所謂根集就量正在執(zhí)行的Java程序可以訪問的引用變量的集合(包括局部變量、參數(shù)、類變量),程序可以使用引用變量訪問對象的屬性和調(diào)用對象的方法。垃圾收集首選需要確定從根開始哪些是可達(dá)的和哪些是不可達(dá)的,從根集可達(dá)的對象都是活動對象,它們不能作為垃圾被回收,這也包括從根集間接可達(dá)的對象。而根集通過任意路徑不可達(dá)的對象符合垃圾收集的條件,應(yīng)該被回收。下面介紹幾個常用的算法。

          1、  引用計(jì)數(shù)法(Reference Counting Collector)

          引用計(jì)數(shù)法是唯一沒有使用根集的垃圾回收的法,該算法使用引用計(jì)數(shù)器來區(qū)分存活對象和不再使用的對象。一般來說,堆中的每個對象對應(yīng)一個引用計(jì)數(shù)器。當(dāng)每一次創(chuàng)建一個對象并賦給一個變量時(shí),引用計(jì)數(shù)器置為1。當(dāng)對象被賦給任意變量時(shí),引用計(jì)數(shù)器每次加1當(dāng)對象出了作用域后(該對象丟棄不再使用),引用計(jì)數(shù)器減1,一旦引用計(jì)數(shù)器為0,對象就滿足了垃圾收集的條件。

          基于引用計(jì)數(shù)器的垃圾收集器運(yùn)行較快,不會長時(shí)間中斷程序執(zhí)行,適宜地必須 實(shí)時(shí)運(yùn)行的程序。但引用計(jì)數(shù)器增加了程序執(zhí)行的開銷,因?yàn)槊看螌ο筚x給新的變量,計(jì)數(shù)器加1,而每次現(xiàn)有對象出了作用域生,計(jì)數(shù)器減1

          2tracing算法(Tracing Collector)

          tracing算法是為了解決引用計(jì)數(shù)法的問題而提出,它使用了根集的概念。基于tracing算法的垃圾收集器從根集開始掃描,識別出哪些對象可達(dá),哪些對象不可達(dá),并用某種方式標(biāo)記可達(dá)對象,例如對每個可達(dá)對象設(shè)置一個或多個位。在掃描識別過程中,基于tracing算法的垃圾收集也稱為標(biāo)記和清除(mark-and-sweep)垃圾收集器.

          3compacting算法(Compacting Collector)

          為了解決堆碎片問題,基于tracing的垃圾回收吸收了Compacting算法的思想,在清除的過程中,算法將所有的對象移到堆的一端,堆的另一端就變成了一個相鄰的空閑內(nèi)存區(qū),收集器會對它移動的所有對象的所有引用進(jìn)行更新,使得這些引用在新的位置能識別原來 的對象。在基于Compacting算法的收集器的實(shí)現(xiàn)中,一般增加句柄和句柄表。  

          4copying算法(Coping Collector)

          該算法的提出是為了克服句柄的開銷和解決堆碎片的垃圾回收。它開始時(shí)把堆分成 一個對象 面和多個空閑面, 程序從對象面為對象分配空間,當(dāng)對象滿了,基于coping算法的垃圾 收集就從根集中掃描活動對象,并將每個 活動對象復(fù)制到空閑面(使得活動對象所占的內(nèi)存之間沒有空閑洞),這樣空閑面變成了對象面,原來的對象面變成了空閑面,程序會在新的對象面中分配內(nèi)存。

          一種典型的基于coping算法的垃圾回收是stop-and-copy算法,它將堆分成對象面和空閑區(qū)域面,在對象面與空閑區(qū)域面的切換過程中,程序暫停執(zhí)行。

          5generation算法(Generational Collector)
            stop-and-copy垃圾收集器的一個缺陷是收集器必須復(fù)制所有的活動對象,這增加了程序等待時(shí)間,這是coping算法低效的原因。在程序設(shè)計(jì)中有這樣的規(guī)律:多數(shù)對象存在的時(shí)間比較短,少數(shù)的存在時(shí)間比較長。因此,generation算法將堆分成兩個或多個,每個子堆作為對象的一代(generation)。由于多數(shù)對象存在的時(shí)間比較短,隨著程序丟棄不使用的對象,垃圾收集器將從最年輕的子堆中收集這些對象。在分代式的垃圾收集器運(yùn)行后,上次運(yùn)行存活下來的對象移到下一最高代的子堆中,由于老一代的子堆不會經(jīng)常被回收,因而節(jié)省了時(shí)間。

          6adaptive算法(Adaptive Collector)

          在特定的情況下,一些垃圾收集算法會優(yōu)于其它算法。基于Adaptive算法的垃圾收集器就是監(jiān)控當(dāng)前堆的使用情況,并將選擇適當(dāng)算法的垃圾收集器。

          透視Java垃圾回收

          1、命令行參數(shù)透視垃圾收集器的運(yùn)行

          2、使用System.gc()可以不管JVM使用的是哪一種垃圾回收的算法,都可以請求Java的垃圾回收。在命令行中有一個參數(shù)-verbosegc可以查看Java使用的堆內(nèi)存的情況,它的格式如下:

          java -verbosegc classfile

            可以看個例子:

          class TestGC
          {
           public static void main(String[] args)
           {
            new TestGC();
            System.gc();
            System.runFinalization();
           }
          }


            在這個例子中,一個新的對象被創(chuàng)建,由于它沒有使用,所以該對象迅速地變?yōu)榭蛇_(dá),程序編譯后,執(zhí)行命令: java -verbosegc TestGC 后結(jié)果為:

          [Full GC 168K->97K(1984K), 0.0253873 secs]

            機(jī)器的環(huán)境為,Windows 2000 + JDK1.3.1,箭頭前后的數(shù)據(jù)168K97K分別表示垃圾收集GC前后所有存活對象使用的內(nèi)存容量,說明有168K-97K=71K的對象容量被回收,括號內(nèi)的數(shù)據(jù)1984K為堆內(nèi)存的總?cè)萘浚占枰臅r(shí)間是0.0253873秒(這個時(shí)間在每次執(zhí)行的時(shí)候會有所不同)。

            2finalize方法透視垃圾收集器的運(yùn)行

            在JVM垃圾收集器收集一個對象之前 ,一般要求程序調(diào)用適當(dāng)?shù)姆椒ㄡ尫刨Y源,但在沒有明確釋放資源的情況下,Java提供了缺省機(jī)制來終止化該對象心釋放資源,這個方法就是finalize()。它的原型為:

          protected void finalize() throws Throwable

            在finalize()方法返回之后,對象消失,垃圾收集開始執(zhí)行。原型中的throws Throwable表示它可以拋出任何類型的異常。

            之所以要使用finalize(),是由于有時(shí)需要采取與Java的普通方法不同的一種方法,通過分配內(nèi)存來做一些具有C風(fēng)格的事情。這主要可以通過"固有方法"來進(jìn)行,它是從Java里調(diào)用非Java方法的一種方式。CC++是目前唯一獲得固有方法支持的語言。但由于它們能調(diào)用通過其他語言編寫的子程序,所以能夠有效地調(diào)用任何東西。在非Java代碼內(nèi)部,也許能調(diào)用Cmalloc()系列函數(shù),用它分配存儲空間。而且除非調(diào)用了free(),否則存儲空間不會得到釋放,從而造成內(nèi)存"漏洞"的出現(xiàn)。當(dāng)然,free()是一個CC++函數(shù),所以我們需要在finalize()內(nèi)部的一個固有方法中調(diào)用它。也就是說我們不能過多地使用finalize(),它并不是進(jìn)行普通清除工作的理想場所。

            在普通的清除工作中,為清除一個對象,那個對象的用戶必須在希望進(jìn)行清除的地點(diǎn)調(diào)用一個清除方法。這與C++"破壞器"的概念稍有抵觸。在C++中,所有對象都會破壞(清除)。或者換句話說,所有對象都"應(yīng)該"破壞。若將C++對象創(chuàng)建成一個本地對象,比如在堆棧中創(chuàng)建(在Java中是不可能的),那么清除或破壞工作就會在"結(jié)束花括號"所代表的、創(chuàng)建這個對象的作用域的末尾進(jìn)行。若對象是用new創(chuàng)建的(類似于Java),那么當(dāng)程序員調(diào)用C++delete命令時(shí)(Java沒有這個命令),就會調(diào)用相應(yīng)的破壞器。若程序員忘記了,那么永遠(yuǎn)不會調(diào)用破壞器,我們最終得到的將是一個內(nèi)存"漏洞",另外還包括對象的其他部分永遠(yuǎn)不會得到清除。

            相反,Java不允許我們創(chuàng)建本地(局部)對象--無論如何都要使用new。但在Java中,沒有"delete"命令來釋放對象,因?yàn)槔占鲿椭覀冏詣俞尫糯鎯臻g。所以如果站在比較簡化的立場,我們可以說正是由于存在垃圾收集機(jī)制,所以Java沒有破壞器。然而,隨著以后學(xué)習(xí)的深入,就會知道垃圾收集器的存在并不能完全消除對破壞器的需要,或者說不能消除對破壞器代表的那種機(jī)制的需要(而且絕對不能直接調(diào)用finalize(),所以應(yīng)盡量避免用它)。若希望執(zhí)行除釋放存儲空間之外的其他某種形式的清除工作,仍然必須調(diào)用Java中的一個方法。它等價(jià)于C++的破壞器,只是沒后者方便。

            下面這個例子向大家展示了垃圾收集所經(jīng)歷的過程,并對前面的陳述進(jìn)行了總結(jié)。

          class Chair {
           static boolean gcrun = false;
           static boolean f = false;
           static int created = 0;
           static int finalized = 0;
           int i;
           Chair() {
            i = ++created;
            if(created == 47)
             System.out.println("Created 47");
           }
           protected void finalize() {
            if(!gcrun) {
             gcrun = true;
             System.out.println("Beginning to finalize after " + created + " Chairs have been created");
            }
            if(i == 47) {
             System.out.println("Finalizing Chair #47, " +"Setting flag to stop Chair creation");
             f = true;
            }
            finalized++;
            if(finalized >= created)
             System.out.println("All " + finalized + " finalized");
           }
          }

          public class Garbage {
           public static void main(String[] args) {
            if(args.length == 0) {
             System.err.println("Usage: \n" + "java Garbage before\n or:\n" + "java Garbage after");
             return;
            }
            while(!Chair.f) {
             new Chair();
             new String("To take up space");
            }
            System.out.println("After all Chairs have been created:\n" + "total created = " + Chair.created +
          ", total finalized = " + Chair.finalized);
            if(args[0].equals("before")) {
              System.out.println("gc():");
              System.gc();
              System.out.println("runFinalization():");
              System.runFinalization();
            }
            System.out.println("bye!");
            if(args[0].equals("after"))
             System.runFinalizersOnExit(true);
           }
          }


            上面這個程序創(chuàng)建了許多Chair對象,而且在垃圾收集器開始運(yùn)行后的某些時(shí)候,程序會停止創(chuàng)建Chair。由于垃圾收集器可能在任何時(shí)間運(yùn)行,所以我們不能準(zhǔn)確知道它在何時(shí)啟動。因此,程序用一個名為gcrun的標(biāo)記來指出垃圾收集器是否已經(jīng)開始運(yùn)行。利用第二個標(biāo)記fChair可告訴main()它應(yīng)停止對象的生成。這兩個標(biāo)記都是在finalize()內(nèi)部設(shè)置的,它調(diào)用于垃圾收集期間。另兩個static變量--created以及finalized--分別用于跟蹤已創(chuàng)建的對象數(shù)量以及垃圾收集器已進(jìn)行完收尾工作的對象數(shù)量。最后,每個Chair都有它自己的(非staticint i,所以能跟蹤了解它具體的編號是多少。編號為47Chair進(jìn)行完收尾工作后,標(biāo)記會設(shè)為true,最終結(jié)束Chair對象的創(chuàng)建過程。(關(guān)于這個例子的更具體的分析和說明請參看《Java編程思想》的第四章)

            關(guān)于垃圾收集的幾點(diǎn)補(bǔ)充

            經(jīng)過上述的說明,可以發(fā)現(xiàn)垃圾回收有以下的幾個特點(diǎn):

            (1)垃圾收集發(fā)生的不可預(yù)知性:由于實(shí)現(xiàn)了不同的垃圾收集算法和采用了不同的收集機(jī)制,所以它有可能是定時(shí)發(fā)生,有可能是當(dāng)出現(xiàn)系統(tǒng)空閑CPU資源時(shí)發(fā)生,也有可能是和原始的垃圾收集一樣,等到內(nèi)存消耗出現(xiàn)極限時(shí)發(fā)生,這與垃圾收集器的選擇和具體的設(shè)置都有關(guān)系。

            (2)垃圾收集的精確性:主要包括2 個方面:(a)垃圾收集器能夠精確標(biāo)記活著的對象;(b)垃圾收集器能夠精確地定位對象之間的引用關(guān)系。前者是完全地回收所有廢棄對象的前提,否則就可能造成內(nèi)存泄漏。而后者則是實(shí)現(xiàn)歸并和復(fù)制等算法的必要條件。所有不可達(dá)對象都能夠可靠地得到回收,所有對象都能夠重新分配,允許對象的復(fù)制和對象內(nèi)存的縮并,這樣就有效地防止內(nèi)存的支離破碎。(3)現(xiàn)在有許多種不同的垃圾收集器,每種有其算法且其表現(xiàn)各異,既有當(dāng)垃圾收集開始時(shí)就停止應(yīng)用程序的運(yùn)行,又有當(dāng)垃圾收集開始時(shí)也允許應(yīng)用程序的線程運(yùn)行,還有在同一時(shí)間垃圾收集多線程運(yùn)行。

            (4)垃圾收集的實(shí)現(xiàn)和具體的JVM 以及JVM的內(nèi)存模型有非常緊密的關(guān)系。不同的JVM 可能采用不同的垃圾收集,而JVM 的內(nèi)存模型決定著該JVM可以采用哪些類型垃圾收集。現(xiàn)在,HotSpot 系列JVM中的內(nèi)存系統(tǒng)都采用先進(jìn)的面向?qū)ο蟮目蚣茉O(shè)計(jì),這使得該系列JVM都可以采用最先進(jìn)的垃圾收集。

            (5)隨著技術(shù)的發(fā)展,現(xiàn)代垃圾收集技術(shù)提供許多可選的垃圾收集器,而且在配置每種收集器的時(shí)候又可以設(shè)置不同的參數(shù),這就使得根據(jù)不同的應(yīng)用環(huán)境獲得最優(yōu)的應(yīng)用性能成為可能。

            針對以上特點(diǎn),我們在使用的時(shí)候要注意:

            (1)不要試圖去假定垃圾收集發(fā)生的時(shí)間,這一切都是未知的。比如,方法中的一個臨時(shí)對象在方法調(diào)用完畢后就變成了無用對象,這個時(shí)候它的內(nèi)存就可以被釋放。

            (2Java中提供了一些和垃圾收集打交道的類,而且提供了一種強(qiáng)行執(zhí)行垃圾收集的方法--調(diào)用System.gc(),但這同樣是個不確定的方法。Java 中并不保證每次調(diào)用該方法就一定能夠啟動垃圾收集,它只不過會向JVM發(fā)出這樣一個申請,到底是否真正執(zhí)行垃圾收集,一切都是個未知數(shù)。

            (3)挑選適合自己的垃圾收集器。一般來說,如果系統(tǒng)沒有特殊和苛刻的性能要求,可以采用JVM的缺省選項(xiàng)。否則可以考慮使用有針對性的垃圾收集器,比如增量收集器就比較適合實(shí)時(shí)性要求較高的系統(tǒng)之中。系統(tǒng)具有較高的配置,有比較多的閑置資源,可以考慮使用并行標(biāo)記/清除收集器。

            (4)關(guān)鍵的也是難把握的問題是內(nèi)存泄漏。良好的編程習(xí)慣和嚴(yán)謹(jǐn)?shù)木幊虘B(tài)度永遠(yuǎn)是最重要的,不要讓自己的一個小錯誤導(dǎo)致內(nèi)存出現(xiàn)大漏洞。

            (5)盡早釋放無用對象的引用。大多數(shù)程序員在使用臨時(shí)變量的時(shí)候,都是讓引用變量在退出活動域(scope)后,自動設(shè)置為null,暗示垃圾收集器來收集該對象,還必須注意該引用的對象是否被監(jiān)聽,如果有,則要去掉監(jiān)聽器,然后再賦空值。

            結(jié)束語

            一般來說,Java開發(fā)人員可以不重視JVM中堆內(nèi)存的分配和垃圾處理收集,但是,充分理解Java的這一特性可以讓我們更有效地利用資源。同時(shí)要注意finalize()方法是Java的缺省機(jī)制,有時(shí)為確保對象資源的明確釋放,可以編寫自己的finalize方法。

           

           

           

          posted @ 2005-12-26 17:46 FinalFantasy 閱讀(1253) | 評論 (2)編輯 收藏

          Problem Statement

          You are given a String[] cityMap representing the layout of a city. The city consists of blocks. The first element of cityMap represents the first row of blocks, etc. A 'B' character indicates a location where there is a bus stop. There will be exactly one 'X' character, indicating your location. All other characters will be '.'. You are also given an int walkingDistance, which is the maximum distance you are willing to walk to a bus stop. The distance should be calculated as the number of blocks vertically plus the number of blocks horizontally. Return the number of bus stops that are within walking distance of your current location.

          Definition

          Class:BusStops
          Method:countStops
          Parameters:String[], int
          Returns:int
          Method signature:int countStops(String[] cityMap, int walkingDistance)
          (be sure your method is public)

          Constraints

          -cityMap will contain between 1 and 50 elements, inclusive.
          -Each element of cityMap will contain between 1 and 50 characters, inclusive.
          -Each element of cityMap will contain the same number of characters.
          -Each character of each element of cityMap will be 'B', 'X', or '.'.
          -There will be exactly one 'X' character in cityMap.
          -walkingDistance will be between 1 and 100, inclusive.

          Examples

          0)

          {"...B.",
           ".....",
           "..X.B",
           ".....",
           "B...."}
          3
          Returns: 2
          You can reach the bus stop at the top (3 units away), or on the right (2 units away). The one in the lower left is 4 units away, which is too far.

          1)

          {"B.B..",
           ".....",
           "B....",
           ".....",
           "....X"}
          8
          Returns: 3
          A distance of 8 can get us anywhere on the map, so we can reach all 3 bus stops.

          2)

          {"BBBBB",
           "BB.BB",
           "B.X.B",
           "BB.BB",
           "BBBBB"}
          1
          Returns: 0
          Plenty of bus stops, but unfortunately we cannot reach any of them.

          3)

          {"B..B..",
           ".B...B",
           "..B...",
           "..B.X.",
           "B.B.B.",
           ".B.B.B"}
          3
          Returns: 7


          說實(shí)話我覺得這一題沒啥意思,超簡單,首先先確定X的位置,再用遍歷數(shù)組找B的位置,再求相減的絕對值然后判斷是否超出給出的最大距離就行了。相對這題PlayCars卻很有意思,到現(xiàn)在我也沒想出除了窮舉以外的一個更好的算法,因?yàn)槲矣X得窮舉可能會超時(shí)。有哪位有其它的辦法的話,請告訴我,大家探討一下,謝謝。好了,不廢話了,下面是這題的答案:

          public class BusStops {
           public static void main(String[] arg){
            BusStops total = new BusStops();
            
              System.out.println(total.countStops({"...B.",".....","..X.B",".....","B...."},3));
           }
           
           public int countStops(String[] cityMap, int walkingDistance){
            int sum= 0;
            int locationX = -1;
            int locationY = -1;
            for(int i=0;i<cityMap.length;i++){
             for(int j=0;j<cityMap[i].length();j++){
              if(cityMap[i].charAt(j)=='X'){
               locationX = i;
               locationY = j;
              }
             }
            }
            for(int i=0;i<cityMap.length;i++){
             for(int j=0;j<cityMap[i].length();j++){
              if(cityMap[i].charAt(j)=='B' && (Math.abs(locationX - i) + Math.abs(locationY - j)<=walkingDistance))
               sum++;
             }
            }
            return sum;
           }
          }
          posted @ 2005-12-21 18:24 FinalFantasy 閱讀(665) | 評論 (1)編輯 收藏

          Problem Statement

           

              

          When a stone is thrown across water, sometimes it will land on the water and bounce rather than falling in right away. Suppose that a stone is thrown a distance of n. On each successive bounce it will travel half the distance as the previous bounce (rounded down to the nearest integer). When it can not travel any further, it falls into the water. If, at any point, the stone lands on an obstruction rather than water, it will not bounce, but will simply deflect and fall into the water. Please look at the figure for further clarification (with black, red and green cells representing banks, obstructions and free water respectively). So, if the stone is thrown a distance 7, it will bounce and travel a distance of 3, then finally a distance of 1, having travelled a total distance of 11 (the green path in the figure). If a stone is thrown a distance of 8, it will reach the opposite bank, and if thrown at distances of 2 or 6 it will hit an obstruction during its travel. These are the three red paths in the figure.



          You are given a String water. An 'X' represents an obstruction, while a '.' represents water free from obstruction. You are to return an int representing the maximum distance a stone can travel and finally fall in the water, without hitting any obstructions, and without reaching the opposite bank (going beyond the end of the string). You may choose any initial distance for the throw, which starts from the left side of the string. A distance of 1 is the first character of the string, etc. If no initial throw will result in the stone landing in the water without hitting an obstruction, return 0.

          Definition

              

          Class:

          SkipStones

          Method:

          maxDistance

          Parameters:

          String

          Returns:

          int

          Method signature:

          int maxDistance(String water)

          (be sure your method is public)

              

           

           

           

          Notes

          -

          Obstructions are at water level, so the stone will not hit any obstructions while it's in the air.

          Constraints

          -

          water will contain between 1 and 50 elements, inclusive.

          -

          Each element of water will contain between 1 and 50 characters, inclusive.

          -

          Each character of each element of water will be 'X' or '.'.

          Examples

          0)

           

              

          "..X.....X..."

          Returns: 11

          This is the example from the problem statement.

          1)

           

              

          "...X..."

          Returns: 3

          If it weren't for the obstruction, we could start with a throw of distance 4, and go a total of 7. But, the best we can do is to throw the stone a distance of 2, and have it skip a distance of 1.

          2)

           

              

          "....X....X...XXXX.X....."

          Returns: 22

          12 + 6 + 3 + 1 = 22, is the best case.

          3)

           

              

          "XXXXXXX.XXX.X.."

          Returns: 15

          Here, an initial throw of 8 is the only way to avoid hitting an obstruction. Notice that the stone finally falls in the water just before reaching the opposite bank.

           

           


          這次的題目可以說并不是太難,也許很多人被全英文的題目給難住了,其實(shí)并不應(yīng)該。像我這個還沒過CET4的人都能看得懂,何況是大家呢:)好了,廢話不多說了,下面是我寫的答案:

          public class SkipStones
          {
           public int sum;
           public int total;
           public int maxDistance(String water)
           {
            for(int i=water.length();i>0;i--)
            {
             total=0;
             sum=0;
             int j=i;
             do
             {
              sum+=j;
              j/=2;
              }while(j!=0);
             if(sum>water.length()) continue;
             else
             {
              j=i;
              int b=j-1;
              while(j!=0)
              {
               if(water.charAt(b)=='X') break;
               else
               {
                total+=j;
                j/=2;
                b+=j;
                }
               }
              }
              if(total==sum) break;
             }
             if(total==sum) return sum;
             else return 0;
            }
            
            
           public static void main(String[] args)
           {
            SkipStones a=new SkipStones();
            System.out.println("The maxdistance is "+a.maxDistance("..X.....X..."));
            }
           }
          posted @ 2005-12-14 16:32 FinalFantasy 閱讀(1673) | 評論 (5)編輯 收藏

          《thinking in java》中一段代碼剖析

          程序代碼

          //chapter03:Garbage.java

          // Demonstration of the garbage

          // collector and finalization

          class Chair {

            static boolean gcrun = false;

            static boolean f = false;

            static int created = 0;

            static int finalized = 0;

            int i;

            Chair() {

              i = ++created;

              if(created == 47)

                System.out.println("Created 47");

            }

            public void finalize() {

              if(!gcrun) {

                // The first time finalize() is called:

                gcrun = true;

                System.out.println(

                  "Beginning to finalize after " +

                  created + " Chairs have been created");

              }

              if(i == 47) {

                System.out.println(

                  "Finalizing Chair #47, " +

                  "Setting flag to stop Chair creation");

                f = true;

              }

              finalized++;

              if(finalized >= created)

                System.out.println(

                  "All " + finalized + " finalized");

            }

          }

          public class Garbage {

            public static void main(String[] args) {

              // As long as the flag hasn't been set,

              // make Chairs and Strings:

              while(!Chair.f) {

                new Chair();

                new String("To take up space");

              }

              System.out.println(

                "After all Chairs have been created:\n" +

                "total created = " + Chair.created +

                ", total finalized = " + Chair.finalized);

              // Optional arguments force garbage

              // collection & finalization:

              if(args.length > 0) {

                if(args[0].equals("gc") &line;&line;

                   args[0].equals("all")) {

                  System.out.println("gc():");

                  System.gc();

                }

                if(args[0].equals("finalize") &line;&line;

                   args[0].equals("all")) {

                  System.out.println("runFinalization():");

                  System.runFinalization();

                }

              }

              System.out.println("bye!");

            }

          } ///:~為什么執(zhí)行java Garbage gc以后,當(dāng)所有對象創(chuàng)建完(比如8000個),這時(shí)只清除了2000個(不定),應(yīng)該只能創(chuàng)建47個對象啊

          分析:

          首先,在一個循環(huán)當(dāng)中創(chuàng)建對象,并且只是創(chuàng)建,而不引用,也就是說這個對象會自動的被系統(tǒng)當(dāng)作垃圾處理掉。但請注意,finalize()方法并不是立刻就會執(zhí)行的,執(zhí)行的時(shí)間完全由系統(tǒng)來決定。所以很有可能的情況是已經(jīng)創(chuàng)建了20000個對象,才開始其中的某一個對象的清除工作(這可能和時(shí)間或者系統(tǒng)內(nèi)容的占用有關(guān))。看finalize()方法中的一段代碼:

              if (!gcrun) {

                  gcrun = true;

                  System.out.println(

                      "\nBeginning to finalize after" + created + "Chairs have been created\nat ");

               }

          就會出現(xiàn)這樣的結(jié)果:

          Beginning to finalize after 25038 Chairs have been created

          這時(shí)對象的創(chuàng)建過程仍在繼續(xù)(因?yàn)橐呀?jīng)Finalize的對象還不滿47個,Chair.f還是false)。所以Chair.created會繼續(xù)增加。

          直到有47個對象被清除了,Chair.f被置成true了,創(chuàng)建對象的循環(huán)才結(jié)束。看main方法中的一段代碼:

              System.out.println(

                  "\nAfter all chairs have been created:\n"

                      + "total created ="

                      + Chair.created

                      + ",total finalized ="

                      + Chair.finalized+"\n");

          如上所說,Chair.created是不斷增加的,而在這段代碼執(zhí)行之前,又會有N個對象被釋放掉了,所以finalized也增加了。

          結(jié)果可能是這樣的:

          total created =29096,total finalized =73

          其實(shí)這一過程和使用的JVM有很大關(guān)系,執(zhí)行結(jié)果可能會很不相同。但有一點(diǎn)是可以肯定的,那就是我們無法確定JVM什么時(shí)候做對象的清除工作(這也是Thinking in java中這段代碼的想要說明的),可能會在這個對象剛剛無用的時(shí)候就清除掉了,也可能滯后幾秒,甚至永遠(yuǎn)不清除。

          結(jié)論:

          不能指望finalize()方法能穩(wěn)定的工作,尤其不能依靠它來做文件的關(guān)閉等操作,由于finalize()的不確定性,往往得不到你想要的結(jié)果。事實(shí)上我們只需要知道所有無用的對象,JVM會自己清除就夠了。省點(diǎn)心思去睡覺豈不是更好的一件事情 :)

          posted @ 2005-11-01 13:05 FinalFantasy 閱讀(819) | 評論 (2)編輯 收藏

           

          洛陽的天氣可真是討厭,昨天好不容易放晴了一天,今天就又下起了大雨,本來計(jì)劃好去買衣服的,現(xiàn)在只能泡湯了。這幾天來上網(wǎng)查了很多的資料,為了組建一個PHP、JSP、ASP的全能平臺,PHP跟JSP的平臺是組建好了,可是ASP怎么樣都不行,好不容易下了個IASP裝上了,配置了之后卻老是出現(xiàn)錯誤。哎NB怎么就不配個專業(yè)版的系統(tǒng)給我呢,這樣我就不用那么費(fèi)勁了,只要把IIS跟Apache整合起來就行了。趁著有點(diǎn)時(shí)間就把用apache組建的PHP、JSP平臺教程整理出來了,說實(shí)話光這兩個都費(fèi)了我好多的勁呀,特別是JSP,網(wǎng)上的教程都不知道是什么年代寫的了,幾乎都不能用了,我廢了好幾天的功夫才把這些零件給找齊,所以還特別記下了下載的地址,要下的就要趕快了!好了,廢話不多說了,往下看吧。對了,另外再多說一句,下面的配置是我安裝我本機(jī)的安裝地址的,如果你的安裝地址跟我的不符,那么你就要一些相應(yīng)的改進(jìn)!還有,如果一下的下載地址無效了,你可以在我這留下你的郵箱,我可以將這些東西發(fā)給你。


          前期準(zhǔn)備: 

          所需軟件列表
          1、apache_2.0.54-win32-x86-no_ssl.exe (Apache web服務(wù)器) http://apache.justdn.org/......2.0.54-win32-x86-no_ssl.exe
          2、php-5.0.5-Win32 (PHP語言解析器)
          4、jdk1.4.2(JAVA 語言環(huán)境)
          5、jakarta-tomcat-5.5.12 (Tomcat JSP解析服務(wù)器) http://mirror.vmmatrix.ne......in/apache-tomcat-5.5.12.exe
          7、mod_jk-1.2.14-apache-2.0.54.so.asc (整合Apache+Tomcat的plus) http://apache.linuxforum.......1.2.14-apache-2.0.54.so.asc(為了找這個文件都把我給找瘋了,網(wǎng)上的教程到處都說要mod_jk_1.2.5_2.0.47.dll,可是我找了兩天死都找不到,后來到apache的官方網(wǎng)站看著生硬的EN去查才找到這么個文件,看文件名直覺就告訴我找對了,現(xiàn)在的apache不都是用so擴(kuò)展了么,而且在那個頁面也說明了這一點(diǎn),要使用還要改名,所以在這里特別指出下載地址,讓大家少走很多的彎路)

          開始安裝:
          一、 Apahce+PHP安裝配置 

          1、安裝apache_2.0.54-win32-x86-no_ssl.exe,為了方便把路徑改為c:\吧,其他都不用管一路next下去。
          2、安裝完成之后,apache服務(wù)自動加載,這時(shí)打開瀏覽器,瀏覽:http://localhost,出現(xiàn)apache歡迎頁面(這步需要將C:\apache2\htdocs目錄中的文件“index.html.en”改為“index.html”,方能顯示);如果這步出現(xiàn)異常,請檢查安裝源文件,重新安裝。
          3. 安裝php-5.0.5-Win32,一般下載的PHP文件為一個免安裝的壓縮包,解壓到C:\PHP就可以。 
          4. 配置PHP和Apache,使之能解析php程序。 
          PHP配置:將C:\PHP\目錄中的“php.ini-dist”改名“php.ini”,然后添加環(huán)境變量。在環(huán)境變量里的classpath中添加“.;c:\php;”,在新建一個“PHPRC”的變量,里面同樣是添加“.;c:\php;” 
          Apache配置: 
          打開C:\apache2\conf\httpd.conf 

          httpd.conf是apache的配置文件,在此配置文件最后添加以下語句,用以支持php程序: 

          ScriptAlias /php/ "C:/PHP/" 

          AddType application/x-httpd-php .php3 

          AddType application/x-httpd-php .php 

          AddType application/x-httpd-php .phtml 

          Action application/x-httpd-php "/php/php.exe" 

          ok,接下來重啟Apache服務(wù)器(如果加載PHP成功,可以在Apache監(jiān)控器中看到Apache/2.0.52(win32) PHP/5.0.4)就可以測試了PHP了,用編輯器編寫如下語句: 
          <?
          phpinfo(); 

          ?> 

          保存文件名為“test.php”到C:\apache2\htdocs目錄,然后打開瀏覽器,瀏覽:http://localhost/test.php,出現(xiàn)PHP基本信息就說明配置成功。嚴(yán)格按以上說明安裝配置,都會一次成功。

          二、安裝JDK和Tomcat

          1. 安裝j2sdk-1_4_2-windows-i586,JDK一定要在Tomcat之前安裝,默認(rèn)安裝路徑就可以。
          2. 安裝Jakarta-Tomcat-5.5.12,默認(rèn)安裝路徑就可以。
          4.設(shè)置環(huán)境變量(桌面->我的電腦->右鍵點(diǎn)擊->選擇“屬性”->高級->環(huán)境變量),所有設(shè)置均在系統(tǒng)變量欄進(jìn)行。
          新建->變量名:JAVA_HOME
          ->變量值:C:\j2sdk1.4.2
          新建->變量名:TOMCAT_HOME
          ->變量值:C:\Program Files\Apache Software Foundation\Tomcat 5.5
          新建->變量名: PATH
          ->變量值:.;C:\j2sdk1.4.2\bin; (前面的“.;”一定要有)
          修改增加環(huán)境變量 CLASSPATH (如果沒有此變量名,則新建)
          ->增加變量值:.;C:\j2sdk1.4.2\lib\dt.jar;C:\j2sdk1.4.2\lib\tool.jar;
          C:\j2sdk1.4.2\lib\NetComponents.jar;
          C:\Program Files\Apache Software Foundation\Tomcat 5.5\common\classes;
          C:\Program Files\Apache Software Foundation\Tomcat 5.5\common\lib;
          C:\Program Files\Apache Software Foundation\Tomcat 5.5\common\lib\servlet-api.jar;(前面的“.;”一定要有)

          5. 啟動Tomcat服務(wù)器,打開瀏覽器,瀏覽:http://localhost:8080/ ,出現(xiàn)Tomcat歡迎頁面;如果這步出現(xiàn)異常,請檢查安裝源文件,重新安裝。

          三、整合Apache+Tomcat服務(wù)器

          1. 復(fù)制mod_jk-1.2.14-apache-2.0.54.so.asc文件到C:\Apache2\modules目錄,并將其文件名改為mod_jk.so。
          2. Apache配置:
          C:\apahce2\conf\httpd.conf
          httpd.conf
          在此配置文件最后添加以下語句,用以支持jsp程序:
          LoadModule jk_module modules/mod_jk.so

          JkWorkersFile "C:/Program Files/Apache Software Foundation/Tomcat 5.5/conf/workers.properties"
          JkMount /servlet/* ajp13
          JkMount /*.jsp ajp13

          還有要在
          DirectoryIndex index.html index.html.var的后面加上default.jsp index.jsp(前面忘了說了,支持PHP還要加上index.php default.php)

          3. 在C:\Program Files\Apache Software Foundation\Tomcat 5.5\conf\目錄下,新建文件名為“workers.properties”的文件,將如下內(nèi)容復(fù)制到新建文件workers.properties中。

          workers.properties
          # 只復(fù)制以下內(nèi)容即可:

          workers.tomcat_home=C:\Program Files\Apache Software Foundation\Tomcat 5.5
          workers.java_home=C:\j2sdk1.4.2
          ps=\
          # worker.list=ajp13
          worker.list=ajp12,ajp13

          worker.ajp12.port=8007
          worker.ajp12.host=localhost
          worker.ajp12.type=ajp12
          worker.ajp12.lbfactor=1

          worker.ajp13.port=8009
          worker.ajp13.host=localhost
          worker.ajp13.type=ajp13
          worker.ajp13.lbfactor=1

          worker.loadbalancer.type=lb

          worker.loadbalancer.balanced_workers=ajp12, ajp13
          worker.inprocess.type=jni
          worker.inprocess.class_path=$(workers.tomcat_home)$(ps)classes
          worker.inprocess.class_path=$(workers.tomcat_home)$(ps)lib$(ps)jaxp.jar

          worker.inprocess.class_path=$(workers.tomcat_home)$(ps)lib$(ps)parser.jar

          worker.inprocess.class_path=$(workers.tomcat_home)$(ps)common$(ps)lib$(ps)jasper.jar

          worker.inprocess.class_path=$(workers.tomcat_home)$(ps)common$(ps)lib$(ps)servlet.jar

          worker.inprocess.class_path=$(workers.tomcat_home)$(ps)common$(ps)lib$(ps)webserver.jar

          worker.inprocess.class_path=$(workers.java_home)$(ps)lib$(ps)tools.jar

          worker.inprocess.cmd_line=-config

          worker.inprocess.cmd_line=$(workers.tomcat_home)/conf/jni_server.xml

          worker.inprocess.cmd_line=-home

          worker.inprocess.cmd_line=$(workers.tomcat_home)

          worker.inprocess.jvm_lib=$(workers.java_home)$(ps)jre$(ps)bin$(ps)classic$(ps)jvm.dll


          worker.inprocess.stdout=$(workers.tomcat_home)$(ps)inprocess.stdout

          worker.inprocess.stderr=$(workers.tomcat_home)$(ps)inprocess.stderr

          worker.inprocess.sysprops=tomcat.home=$(workers.tomcat_home)

          接下來重啟Tomcat和Apache服務(wù)器(必須先重啟Tomcat再重啟Apache,不然會出錯,如果加載JK成功,這個時(shí)候你可以在Apache監(jiān)控器中看到Apache/2.0.52(win32) PHP/5.0.4 mod_jk/1.2.8)就可以測試了,把Tomcat的webapps這個目錄拷貝到Apache的htdocs目錄下面,然后直接在瀏覽器地址欄輸入:http://localhost/webappshttp://localhost:8080如果顯示的頁面一樣就說明成功了。

          剩下的就是連接MySQL了,但是本人不才一個叫mm.mysql-2.0.4-bin.jar的文件怎么也找不到,只找到了個mysql-connector-java-3.1.5-gamma-bin.jar的文件,可是我試過了一點(diǎn)用都沒有,所以連接數(shù)據(jù)庫的教程等我試驗(yàn)成功再說拉!如果哪位高人能救救我的告訴我mm.mysql-2.0.4-bin.jar的下載地址或者告訴我IASP到底改如何配置,我真是感激不盡。


          posted @ 2005-10-06 19:28 FinalFantasy 閱讀(4319) | 評論 (6)編輯 收藏

          主站蜘蛛池模板: 永清县| 白玉县| 阿坝县| 大同市| 大厂| 泗水县| 武定县| 盐津县| 汶川县| 临桂县| 南安市| 光泽县| 桦南县| 庄河市| 浮山县| 长顺县| 当阳市| 塘沽区| 盐源县| 南和县| 惠州市| 高平市| 济源市| 清镇市| 临猗县| 富锦市| 宁陵县| 长武县| 华亭县| 滨海县| 忻城县| 共和县| 新巴尔虎右旗| 苍梧县| 璧山县| 恩施市| 丰都县| 安远县| 德清县| 蛟河市| 大厂|