面接に加点するだけでなく、Java WeakReferenceの理解と使用


sourceFrom:http://www.tuicool.com/articles/imyueq
前言:投稿を見て、海外の技術面接官がsenior java developerを面接したとき、weak referenceに関する質問をしました.彼はweak referenceが何なのか、どのように使われているのかを完全に説明することを望んでいません.ただ、このconceptとjavaのGCに関する話をすることを望んでいます.残念なことに、5年以上のjava開発経験を持つ20人以上の面接者のうち、weak referenceの存在を知っているのは2人だけで、そのうち1人だけが実際に彼を使ったことがある.間違いなくインターネットの目には、weak referenceに対する理解と応用が面接でこのインターネットに多くのプラス点を与えた.だから、私のこの技術に対する理解と使用をこのブログにまとめた.読者と自分がこの招待状を読むことと書くことを通じて、後の仕事と面接で加点を得ることができることを望んでいます.
Javaでは、オブジェクトoが作成するとHeapに格納されます.GCが実行されると、oへの参照がないことが判明すると、oはメモリスペースを空けるために回収されます.あるいは、1つのオブジェクトが回収されると、2つの条件を満たす必要があります.1)参照がない2)GCが実行されます.
現実的にコードを書くとき、あるオブジェクトを指すrefereceをすべて空にすることで、このオブジェクトが次のGCで実行されるときに回収されることを保証することが多い(java-verbose:gcでgcの動作を観察することができる)
Object c = new Car();
c=null;

しかし、手動で空のオブジェクトを置くことはプログラマーにとって、煩雑で自動回収の理念に反する.  簡単な場合、手動で空にするにはプログラマーは必要ありません.javaでは、簡単なオブジェクトに対して、呼び出すメソッドの実行が完了すると、その参照がstackからpopupされるので、次のGC実行時に回収することができます.
ただし、特殊な例外もあります.cacheを使用する場合、cacheのオブジェクトがプログラム実行に必要なため、プログラムが実行されている限り、cacheでの参照はGCに与えられません(あるいは、cacheでのreferenceはメインプログラムと同じlife cycleを持っています).cacheでのreferenceが多くなるにつれて、GCで回収できないobjectも多くなります.自動回収はできない.これらのobjectを回収する必要がある場合,これらのobjectを回収するタスクはプログラム作成者に任せるしかない.しかしこれはGCの本質(自動回収可能なobjects)に反する.
したがって、javaには、前の例のstrong referenceに対してweak referenceが導入されている.
Object c = new Car(); //  c   car object, car object      

 1つのオブジェクトがweak referenceのみで指向され、他のstrong referenceが指向されていない場合、GCが実行されると、このオブジェクトは回収されます.weak referenceの構文は次のとおりです.
WeakReference<Car> weakCar = new WeakReference(Car)(car);

 Weak reference参照のobjectを取得するには、まず回収されたかどうかを判断する必要があります.
weakCar.get();

 この方法が空の場合、weakCarが指すオブジェクトが回収されたことを示す.
次に例を示します.
package weakreference;
/**
 * @author wison
 */
public class Car {
  private double price;
  private String colour;
  
  public Car(double price, String colour){
    this.price = price;
    this.colour = colour;
  }
  
  public double getPrice() {
    return price;
  }
  public void setPrice(double price) {
    this.price = price;
  }
  public String getColour() {
    return colour;
  }
  public void setColour(String colour) {
    this.colour = colour;
  }
  
  public String toString(){
    return colour +"car costs $"+price;
  }
  
}
package weakreference;

import java.lang.ref.WeakReference;

/**
 * @author wison
 */
public class TestWeakReference {

  
  public static void main(String[] args) {
    
    Car car = new Car(22000,"silver");
    WeakReference<Car> weakCar = new WeakReference<Car>(car);
    
    int i=0;
    
    while(true){
      if(weakCar.get()!=null){
        i++;
        System.out.println("Object is alive for "+i+" loops - "+weakCar);
      }else{
        System.out.println("Object has been collected.");
        break;
      }
    }
  }

}

上記の例では、プログラムの実行時間が経過すると、プログラムは「Object has been collected.」と印刷する、weak referenceが指すオブジェクトが回収される.
注目すべき点は、carがオブジェクトを参照し、carがstrong referenceである場合でも、weak reference weakCarが指すオブジェクトは回収されます.これはjavaのコンパイラがwhileサイクルに入ったことを発見した後、carが使用されていないことを発見したため、最適化が行われたためです.TestWeakReference.javaを次のように変更します.
package weakreference;

import java.lang.ref.WeakReference;

/**
 * @author wison
 */
public class TestWeakReference {

  
  public static void main(String[] args) {
    
    Car car = new Car(22000,"silver");
    WeakReference<Car> weakCar = new WeakReference<Car>(car);
    
    int i=0;
    
    while(true){
      System.out.println("here is the strong reference 'car' "+car);
      if(weakCar.get()!=null){
        i++;
        System.out.println("Object is alive for "+i+" loops - "+weakCar);
      }else{
        System.out.println("Object has been collected.");
        break;
      }
    }
  }

}

 Weak referenceが指すobjectは回収されません.strong reference carがそれを指しているからです.
*WeakReferenceの特徴の1つは、GCが実行する不確実性によって決定されるため、いつ回収されるかが不確定であることである.そのため、一般的にweak referenceで参照されるオブジェクトは、cacheによって価値があり、再構築されやすく、メモリの対象が消費される.
ReferenceQueue
Weak referenceが指すオブジェクトが回収された後、weak reference自体は実際には役に立たない.javaは、これらが指すオブジェクトが回収されたreferenceを保存するためにReferenceQueueを提供する.使用法は、WeakReferenceを定義する際にReferenceQueueのオブジェクトをパラメータとしてコンストラクタに伝達する.
その他のタイプのreferences
-SoftReference
ソフトウェアreferenceはweak referenceと同じですが、GCで回収されるには、システムメモリが不足している場合(GCはどのようにシステムメモリが不足していると判定しますか?このthresholdを構成できるパラメータがありますか?)ソフトウェアreferenceが指すobjectが回収されるという条件が必要です.この特性があるからこそ、ソフトウェアreferenceはweak referenceよりcache objectsのreferenceに適している.できるだけretain cached objectsを再構築するのにかかる時間と消費を減らすことができるからだ.
-phantomReference
これはまだシーンを応用するとは思わなかったので、先に言わないでください.実践の中で使った人がいたら、分かち合いを歓迎します.
WeakHashMap to be continued