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

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

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

    Fantasy's World

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

      BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
      6 Posts :: 0 Stories :: 16 Comments :: 0 Trackbacks

    2005年12月29日 #

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

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

    2005年12月26日 #

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

    引言

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

    垃圾收集的意義

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

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

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

    垃圾收集的算法分析

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

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

    1、  引用計數法(Reference Counting Collector)

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

    基于引用計數器的垃圾收集器運行較快,不會長時間中斷程序執行,適宜地必須 實時運行的程序。但引用計數器增加了程序執行的開銷,因為每次對象賦給新的變量,計數器加1,而每次現有對象出了作用域生,計數器減1。

    2、tracing算法(Tracing Collector)

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

    3compacting算法(Compacting Collector)

    為了解決堆碎片問題,基于tracing的垃圾回收吸收了Compacting算法的思想,在清除的過程中,算法將所有的對象移到堆的一端,堆的另一端就變成了一個相鄰的空閑內存區,收集器會對它移動的所有對象的所有引用進行更新,使得這些引用在新的位置能識別原來 的對象。在基于Compacting算法的收集器的實現中,一般增加句柄和句柄表?! ?SPAN lang=EN-US>

    4、copying算法(Coping Collector)

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

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

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

    6、adaptive算法(Adaptive Collector)

    在特定的情況下,一些垃圾收集算法會優于其它算法?;?SPAN lang=EN-US>Adaptive算法的垃圾收集器就是監控當前堆的使用情況,并將選擇適當算法的垃圾收集器。

    透視Java垃圾回收

    1、命令行參數透視垃圾收集器的運行

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

    java -verbosegc classfile

      可以看個例子:

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


      在這個例子中,一個新的對象被創建,由于它沒有使用,所以該對象迅速地變為可達,程序編譯后,執行命令: java -verbosegc TestGC 后結果為:

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

      機器的環境為,Windows 2000 + JDK1.3.1,箭頭前后的數據168K97K分別表示垃圾收集GC前后所有存活對象使用的內存容量,說明有168K-97K=71K的對象容量被回收,括號內的數據1984K為堆內存的總容量,收集所需要的時間是0.0253873秒(這個時間在每次執行的時候會有所不同)。

      2、finalize方法透視垃圾收集器的運行

      在JVM垃圾收集器收集一個對象之前 ,一般要求程序調用適當的方法釋放資源,但在沒有明確釋放資源的情況下,Java提供了缺省機制來終止化該對象心釋放資源,這個方法就是finalize()。它的原型為:

    protected void finalize() throws Throwable

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

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

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

      相反,Java不允許我們創建本地(局部)對象--無論如何都要使用new。但在Java中,沒有"delete"命令來釋放對象,因為垃圾收集器會幫助我們自動釋放存儲空間。所以如果站在比較簡化的立場,我們可以說正是由于存在垃圾收集機制,所以Java沒有破壞器。然而,隨著以后學習的深入,就會知道垃圾收集器的存在并不能完全消除對破壞器的需要,或者說不能消除對破壞器代表的那種機制的需要(而且絕對不能直接調用finalize(),所以應盡量避免用它)。若希望執行除釋放存儲空間之外的其他某種形式的清除工作,仍然必須調用Java中的一個方法。它等價于C++的破壞器,只是沒后者方便。

      下面這個例子向大家展示了垃圾收集所經歷的過程,并對前面的陳述進行了總結。

    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);
     }
    }


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

      關于垃圾收集的幾點補充

      經過上述的說明,可以發現垃圾回收有以下的幾個特點:

     ?。?SPAN lang=EN-US>1
    )垃圾收集發生的不可預知性:由于實現了不同的垃圾收集算法和采用了不同的收集機制,所以它有可能是定時發生,有可能是當出現系統空閑CPU資源時發生,也有可能是和原始的垃圾收集一樣,等到內存消耗出現極限時發生,這與垃圾收集器的選擇和具體的設置都有關系。

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

     ?。?SPAN lang=EN-US>4)垃圾收集的實現和具體的JVM 以及JVM的內存模型有非常緊密的關系。不同的JVM 可能采用不同的垃圾收集,而JVM 的內存模型決定著該JVM可以采用哪些類型垃圾收集?,F在,HotSpot 系列JVM中的內存系統都采用先進的面向對象的框架設計,這使得該系列JVM都可以采用最先進的垃圾收集。

     ?。?SPAN lang=EN-US>5)隨著技術的發展,現代垃圾收集技術提供許多可選的垃圾收集器,而且在配置每種收集器的時候又可以設置不同的參數,這就使得根據不同的應用環境獲得最優的應用性能成為可能。

      針對以上特點,我們在使用的時候要注意:

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

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

     ?。?SPAN lang=EN-US>3)挑選適合自己的垃圾收集器。一般來說,如果系統沒有特殊和苛刻的性能要求,可以采用JVM的缺省選項。否則可以考慮使用有針對性的垃圾收集器,比如增量收集器就比較適合實時性要求較高的系統之中。系統具有較高的配置,有比較多的閑置資源,可以考慮使用并行標記/清除收集器。

      (4)關鍵的也是難把握的問題是內存泄漏。良好的編程習慣和嚴謹的編程態度永遠是最重要的,不要讓自己的一個小錯誤導致內存出現大漏洞。

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

      結束語

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

     

     

     

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

    2005年12月21日 #

    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


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

    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 閱讀(664) | 評論 (1)編輯 收藏

    2005年12月14日 #

    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.

     

     


    這次的題目可以說并不是太難,也許很多人被全英文的題目給難住了,其實并不應該。像我這個還沒過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 閱讀(1671) | 評論 (5)編輯 收藏

    2005年11月1日 #

    《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!");

      }

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

    分析:

    首先,在一個循環當中創建對象,并且只是創建,而不引用,也就是說這個對象會自動的被系統當作垃圾處理掉。但請注意,finalize()方法并不是立刻就會執行的,執行的時間完全由系統來決定。所以很有可能的情況是已經創建了20000個對象,才開始其中的某一個對象的清除工作(這可能和時間或者系統內容的占用有關)???SPAN lang=EN-US>finalize()方法中的一段代碼:

        if (!gcrun) {

            gcrun = true;

            System.out.println(

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

         }

    就會出現這樣的結果:

    Beginning to finalize after 25038 Chairs have been created

    這時對象的創建過程仍在繼續(因為已經Finalize的對象還不滿47個,Chair.f還是false)。所以Chair.created會繼續增加。

    直到有47個對象被清除了,Chair.f被置成true了,創建對象的循環才結束。看main方法中的一段代碼:

        System.out.println(

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

                + "total created ="

                + Chair.created

                + ",total finalized ="

                + Chair.finalized+"\n");

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

    結果可能是這樣的:

    total created =29096,total finalized =73

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

    結論:

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

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

    2005年10月6日 #

     

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


    前期準備: 

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

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

    1、安裝apache_2.0.54-win32-x86-no_ssl.exe,為了方便把路徑改為c:\吧,其他都不用管一路next下去。
    2、安裝完成之后,apache服務自動加載,這時打開瀏覽器,瀏覽:http://localhost,出現apache歡迎頁面(這步需要將C:\apache2\htdocs目錄中的文件“index.html.en”改為“index.html”,方能顯示);如果這步出現異常,請檢查安裝源文件,重新安裝。
    3. 安裝php-5.0.5-Win32,一般下載的PHP文件為一個免安裝的壓縮包,解壓到C:\PHP就可以。 
    4. 配置PHP和Apache,使之能解析php程序。 
    PHP配置:將C:\PHP\目錄中的“php.ini-dist”改名“php.ini”,然后添加環境變量。在環境變量里的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服務器(如果加載PHP成功,可以在Apache監控器中看到Apache/2.0.52(win32) PHP/5.0.4)就可以測試了PHP了,用編輯器編寫如下語句: 
    <?
    phpinfo(); 

    ?> 

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

    二、安裝JDK和Tomcat

    1. 安裝j2sdk-1_4_2-windows-i586,JDK一定要在Tomcat之前安裝,默認安裝路徑就可以。
    2. 安裝Jakarta-Tomcat-5.5.12,默認安裝路徑就可以。
    4.設置環境變量(桌面->我的電腦->右鍵點擊->選擇“屬性”->高級->環境變量),所有設置均在系統變量欄進行。
    新建->變量名:JAVA_HOME
    ->變量值:C:\j2sdk1.4.2
    新建->變量名:TOMCAT_HOME
    ->變量值:C:\Program Files\Apache Software Foundation\Tomcat 5.5
    新建->變量名: PATH
    ->變量值:.;C:\j2sdk1.4.2\bin; (前面的“.;”一定要有)
    修改增加環境變量 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服務器,打開瀏覽器,瀏覽:http://localhost:8080/ ,出現Tomcat歡迎頁面;如果這步出現異常,請檢查安裝源文件,重新安裝。

    三、整合Apache+Tomcat服務器

    1. 復制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”的文件,將如下內容復制到新建文件workers.properties中。

    workers.properties
    # 只復制以下內容即可:

    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服務器(必須先重啟Tomcat再重啟Apache,不然會出錯,如果加載JK成功,這個時候你可以在Apache監控器中看到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的文件,可是我試過了一點用都沒有,所以連接數據庫的教程等我試驗成功再說拉!如果哪位高人能救救我的告訴我mm.mysql-2.0.4-bin.jar的下載地址或者告訴我IASP到底改如何配置,我真是感激不盡。


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

    主站蜘蛛池模板: 亚洲天堂一区二区三区| 亚洲人成毛片线播放| 久久久久免费精品国产小说| 亚洲美女自拍视频| 在线观看人成视频免费| 真人无码作爱免费视频| 精品国产综合成人亚洲区| 2015日韩永久免费视频播放| 亚洲国产精品成人AV在线| 亚洲日韩精品一区二区三区| 亚洲电影在线免费观看| 麻豆69堂免费视频| 亚洲黄色片免费看| 国产免费私拍一区二区三区| 中文字幕无码毛片免费看| 国产成人精品日本亚洲网址| 亚洲毛片不卡av在线播放一区| 99视频在线免费看| 国产精品亚洲专区无码唯爱网 | 在线观看成人免费视频不卡| 成a人片亚洲日本久久| 亚洲精品成人av在线| 免费国产在线观看老王影院| 日韩插啊免费视频在线观看 | 亚洲人成在线中文字幕| 亚洲成a人一区二区三区| 皇色在线视频免费网站| 成人无码视频97免费| 亚洲精品无码av中文字幕| 亚洲电影一区二区| 亚洲毛片不卡av在线播放一区| 99无码人妻一区二区三区免费| 精品国产呦系列在线观看免费| 亚洲一卡二卡三卡| 久久久久亚洲精品影视| 亚洲VA综合VA国产产VA中| 成人免费午夜视频| 永久在线免费观看| 午夜网站在线观看免费完整高清观看| 国产成人亚洲精品91专区高清| 亚洲AV无码国产精品色|