jdk8源碼分析筆記1 --> Object.class

第一章節,不能再往前了!java

前言:緩存

學習jdk源碼,提升本身的code能力ide

源碼學習的過程是經過,對自身的提高遠比貼吧來的更準確,更實用。源碼分析

注:所有代碼會在帖子最後面貼出學習

開山第一斧:Object.classui

學習思路,熟悉方法的使用和實現原理this

@Test
  public void testGetClass() {
    User user = new User();
    Class<? extends User> userClass = user.getClass();
    System.out.println(userClass.getName());
    System.out.println(userClass.getSimpleName());
    System.out.println(userClass.getTypeName());
    /**
     * ....能夠獲取更多信息
     * 執行結果
     * com.daly.demo.test.TestObject$User
     * User
     * com.daly.demo.test.TestObject$User
     */
  }
@Test
  public void testHashCode() {
    User user1 = new User(1, "jack");
    User user2 = new User(1, "jack");
    HashSet<User> set = new HashSet<>();
    set.add(user1);
    set.add(user2);
    System.out.println("user1.hashcode =" + user1.hashCode());
    System.out.println("user2.hashcode =" + user2.hashCode());
    System.out.println("uesr1.equals(user2) is " + user1.equals(user2));
    System.out.println("set.size = " + set.size());
    /**
     * 在使用HashMap,HashSet時,經過比較hahscode的值來判斷是否相等
     * 運行結果
     * user1.hashcode =1023487453
     * user2.hashcode =1865127310
     * uesr1.equals(user2) is false
     * set.size = 2
     */
  }

僅重寫了equals方法,再使用set時,沒法判斷重複對象,由於,他們的hashcode值不同,被認爲是不一樣的key,spa

@Test
  public void testHashCodeOverride() {
    UserOverride user1 = new UserOverride(1, "jack");
    UserOverride user2 = new UserOverride(1, "jack");
    HashSet<UserOverride> set = new HashSet<>();
    set.add(user1);
    set.add(user2);
    System.out.println("user1.hashcode =" + user1.hashCode());
    System.out.println("user2.hashcode =" + user2.hashCode());
    System.out.println("uesr1.equals(user2) is " + user1.equals(user2));
    System.out.println("set.size =" + set.size());
    /**
     * 在使用HashMap,HashSet時,經過比較hahscode的值來判斷是否相等
     * 運行結果
     * user1.hashcode =1023487453
     * user2.hashcode =1865127310
     * uesr1.equals(user2) is true
     * set.size =2
     */
  }

同時重寫equals和hashcode方法,代碼以下:.net

@Test
  public void testHashCodeOverride() {
    UserOverride user1 = new UserOverride(1, "jack");
    UserOverride user2 = new UserOverride(1, "jack");
    HashSet<UserOverride> set = new HashSet<>();
    set.add(user1);
    set.add(user2);
    System.out.println("user1.hashcode =" + user1.hashCode());
    System.out.println("user2.hashcode =" + user2.hashCode());
    System.out.println("uesr1.equals(user2) is " + user1.equals(user2));
    System.out.println("set.size =" + set.size());
    /**
     * 在使用HashMap,HashSet時,經過比較hahscode的值來判斷是否相等
     * 運行結果
     * user1.hashcode =3254238
     * user2.hashcode =3254238
     * uesr1.equals(user2) is true
     * set.size =1
     */
  }
//jdk源碼的equals方法實現,是比較內存的地址,在比較繼承
//在比較對象是否相等,須要重寫這個方法,並且還要重寫hashcode方法,緣由是set在判斷對象是否已存在時,是經過對象的hashcode來判斷的
public boolean equals(Object obj) {
    return (this == obj);
}
@Test
  public void testEquals() {
    int i1 = 127,i2 = 127;
    Integer ibox1 = 128, ibox2 = 128;
    System.out.println("int i1 = 127,i2 = 127;            --> i1 == i2            is " + (i1 == i2));
    System.out.println("Integer ibox1 = 128, ibox2 = 128; --> ibox1 == ibox2      is " + (ibox1 == ibox2));
    System.out.println("Integer ibox1 = 128, ibox2 = 128; --> ibox1.equals(ibox2) is " + ibox1.equals(ibox2));
    /**
     * 由於Integer在重寫equals方法時,
     * 執行結果
     * int i1 = 127,i2 = 127;            --> i1 == i2            is true
     * Integer ibox1 = 128, ibox2 = 128; --> ibox1 == ibox2      is false
     * Integer ibox1 = 128, ibox2 = 128; --> ibox1.equals(ibox2) is true
     */
  }
//jdk8 源碼部分
//在進行自動拆裝箱時,編譯器會使用Integer.valueof()來建立Integer實例。
//代碼解釋,先從緩存拿,沒有拿到就建立一個Integer返回,Integer的取值範圍在-128~127全部超過127時,就會出現陷阱了
public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}
@Test
  public void testCloneShallow() throws CloneNotSupportedException {
    Role role = new Role(1, "normal");
    User user = new User(1, "jack");
    user.setRole(role);
    User userClone;
    userClone = (User) user.clone();
    System.out.println("user.equals(userClone)                 is " + user.equals(userClone));
    System.out.println("user == userClone                      is " + (user == userClone));
    System.out.println( "user.getRole() == userClone.getRole() is " + (user.getRole() == userClone.getRole()));
    System.out.println("------------ 分割線 -----------");
    user.getRole().setRoleName(user.getRole().getRoleName().toUpperCase());
    System.out.println("user.getRole().getRoleName()      is "+user.getRole().getRoleName());
    System.out.println("userClone.getRole().getRoleName() is "+userClone.getRole().getRoleName());
    /**
     * 此處的user.clone()爲淺拷貝,因此user和userClone的UserOverride是指向同一內存地址的對象
     * 執行結果
     * 由於User沒有重寫equals方法,因此 equals的結果跟== 都爲false
     * user.equals(userClone)                 is false
     * user == userClone                      is false
     * user.getRole() == userClone.getRole() is true
     * ------------ 分割線 -----------
     * user.getRole().getRoleName()      is NORMAL
     * userClone.getRole().getRoleName() is NORMAL
     */
  }
@Test
public void testCloneDeep() throws CloneNotSupportedException {
  RoleOverride role = new RoleOverride(1, "normal");
  UserOverride user = new UserOverride(1, "jack");
  user.setRoleOverride(role);
  UserOverride userClone;
  userClone = (UserOverride) user.clone();
  System.out.println("user.equals(userClone)  is " + user.equals(userClone));
  System.out.println("user == userClone       is " + (user == userClone));
  System.out.println("they'er getUserOverride is " +
      (user.getRoleOverride() == userClone.getRoleOverride()));
  System.out.println("------------ 分割線 -----------");
  user.getRoleOverride().setRoleName(user.getRoleOverride().getRoleName().toUpperCase());
  System.out.println("user.getRole().getRoleName() is "+user.getRoleOverride().getRoleName());
  System.out.println("userClone.getRole().getRoleName() is "+userClone.getRoleOverride().getRoleName());
  /**
   * 此處的user.clone()爲淺拷貝,因此user和userClone的UserOverride是指向同一內存地址的對象
   * 執行結果
   * 由於 RoleOverride 重寫了equals方法,因此 equals的結果爲true, == 結果爲 false
   * user.equals(userClone)  is true
   * user == userClone       is false
   * they'er getUserOverride is false
   * ------------ 分割線 -----------
   * user.getRole().getRoleName() is NORMAL
   * userClone.getRole().getRoleName() is normal
   */
}

深度clone的關鍵代碼以下:線程

@Override
protected Object clone() throws CloneNotSupportedException {
  Object clone = super.clone();
  RoleOverride roleOverride = ((UserOverride)clone).getRoleOverride();
  ((UserOverride)clone).setRoleOverride((RoleOverride) roleOverride.clone());
  return clone;
}

jdk8 的Object的toString方法的源碼以下

//返回的是className@哈希值
//在建立類時,須要重寫這個方法
public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

notify喚醒了其中一個等待的線程,

/**
   * 來自博客 https://blog.csdn.net/u014658905/article/details/81035870
   */
  @Test
  public void testNotify() throws InterruptedException {
    final NotificationTest test = new NotificationTest();
    Runnable waitTask = () -> {
      try {
        test.shouldGo();
      } catch (InterruptedException ex) {
        System.out.println(ex.getMessage());
      }
      System.out.println(Thread.currentThread().getName() + " finished Execution");
    };
    Runnable notifyTask = () -> {
      test.go2();
      System.out.println(Thread.currentThread().getName() + " finished Execution");
    };
    Thread t1 = new Thread(waitTask, "WT1"); //will wait
    Thread t2 = new Thread(waitTask, "WT2"); //will wait
    Thread t3 = new Thread(waitTask, "WT3"); //will wait
    Thread t4 = new Thread(notifyTask, "NT1"); //will notify
    //starting all waiting thread
    t1.start();
    t2.start();
    t3.start();
    //pause to ensure all waiting thread started successfully
    sleep(200);
    //starting notifying thread
    t4.start();
    /**
     * 運行結果
     * WT1 is going to wait on this object
     * WT2 is going to wait on this object
     * WT3 is going to wait on this object
     * NT1 is going to notify all or one thread waiting on this object
     * NT1 finished Execution
     * WT1 is woken up
     * WT1 finished Execution
     */
  }

notifyAll喚醒了所有等待的線程

/**
   * 來自博客 https://blog.csdn.net/u014658905/article/details/81035870
   */
  @Test
  public void testNotifyAll() throws InterruptedException {
    final NotificationTest test = new NotificationTest();
    Runnable waitTask = () -> {
      try {
        test.shouldGo();
      } catch (InterruptedException ex) {
        System.out.println(ex.getMessage());
      }
      System.out.println(Thread.currentThread().getName() + " finished Execution");
    };
    Runnable notifyTask = () -> {
      test.go();
      System.out.println(Thread.currentThread().getName() + " finished Execution");
    };
    Thread t1 = new Thread(waitTask, "WT1"); //will wait
    Thread t2 = new Thread(waitTask, "WT2"); //will wait
    Thread t3 = new Thread(waitTask, "WT3"); //will wait
    Thread t4 = new Thread(notifyTask, "NT1"); //will notify
    //starting all waiting thread
    t1.start();
    t2.start();
    t3.start();
    //pause to ensure all waiting thread started successfully
    sleep(200);
    //starting notifying thread
    t4.start();
    /**
     * 運行結果
     * WT1 is going to wait on this object
     * WT2 is going to wait on this object
     * WT3 is going to wait on this object
     * NT1 is going to notify all or one thread waiting on this object
     * NT1 finished Execution
     * WT3 is woken up
     * WT3 finished Execution
     * WT2 is woken up
     * WT2 is going to wait on this object
     * WT1 is woken up
     * WT1 is going to wait on this object
     */
  }
/**
   * 除了耗時完成後自動喚醒,還能夠被notify和notifyAll喚醒
   * notify和notifyAll喚醒方式,如上面的例子所示
   * @throws InterruptedException
   */
  @Test
  public void testWait() throws InterruptedException {
    Runnable myThread = () -> {
      synchronized (this) {
        try {
          System.out.println("myThread start at "+ new SimpleDateFormat("mm:ss").format(new Date()));
          //wait(5000);//5秒鐘以後喚醒當前線程.繼續執行
          wait();//一直等待
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println("myThread run end");
      }
    };

    Thread t1 = new Thread(myThread, "t1"); //will wait
    synchronized (t1) {
      t1.start();
      t1.wait(2000); //2秒鐘以後,喚醒了main線程繼續執行
      //t1.wait(2000,1000);//1000000*2000+1000 毫微秒鐘以後,喚醒了main線程,徹底體現不出來這第二個參數的意義
      //t1.wait();//mian線程一直等待,沒有被其餘線程喚醒
      System.out.println("mainThread wake up at "+ new SimpleDateFormat("mm:ss").format(new Date()));
      System.out.println("main run end");
    }
    /**
     * 運行結果以下
     * 當myThread被提早喚醒時,後面的代碼不會被執行
     * myThread start at 38:57
     * myThread run end
     * mainThread wake up at 39:02
     * main run end
     * 或
     *myThread start at 41:52
     * mainThread wake up at 41:54
     * main run end
     */
  }

最後一個方法就是finalize

/**
   * 很經典的GC回收機制實例
   */
  @Test
  public void testFinalize() throws InterruptedException {
    // 新建對象,由於SAVE_HOOK指向這個對象,對象此時的狀態是(reachable,unfinalized)
    GC.SAVE_HOOK = new GC();
    //將SAVE_HOOK設置成null,此時剛纔建立的對象就不可達了,由於沒有句柄再指向它了,對象此時狀態是(unreachable,unfinalized)
    GC.SAVE_HOOK = null;
    //強制系統執行垃圾回收,系統發現剛纔建立的對象處於unreachable狀態,並檢測到這個對象的類覆蓋了finalize方法,所以把這個對象放入F-Queue隊列,由低優先級線程執行它的finalize方法,此時對象的狀態變成(unreachable, finalizable)或者是(finalizer-reachable,finalizable)
    System.gc();
    // sleep,目的是給低優先級線程從F-Queue隊列取出對象並執行其finalize方法提供機會。在執行完對象的finalize方法中的super.finalize()時,對象的狀態變成(unreachable,finalized)狀態,但接下來在finalize方法中又執行了SAVE_HOOK = this;這句話,又有句柄指向這個對象了,對象又可達了。所以對象的狀態又變成了(reachable, finalized)狀態。
    Thread.sleep(500);
    // 這裏樓主說對象處於(reachable,finalized)狀態應該是合理的。對象的finalized方法被執行了,所以是finalized狀態。又由於在finalize方法是執行了SAVE_HOOK=this這句話,原本是unreachable的對象,又變成reachable了。
    if (null != GC.SAVE_HOOK) { //此時對象應該處於(reachable, finalized)狀態
      // 這句話會輸出,注意對象由unreachable,通過finalize復活了。
      System.out.println("Yes , I am still alive");
    } else {
      System.out.println("No , I am dead");
    }
    // 再一次將SAVE_HOOK放空,此時剛纔復活的對象,狀態變成(unreachable,finalized)
    GC.SAVE_HOOK = null;
    // 再一次強制系統回收垃圾,此時系統發現對象不可達,雖然覆蓋了finalize方法,但已經執行過了,所以直接回收。
    System.gc();
    // 爲系統回收垃圾提供機會
    Thread.sleep(500);
    if (null != GC.SAVE_HOOK) {
      // 這句話不會輸出,由於對象已經完全消失了。
      System.out.println("Yes , I am still alive");
    } else {
      System.out.println("No , I am dead");
    }
  }

Object.class的全部方法都舉了栗子,歡迎你們指正。

補充: 比較obj.hashcode 和 System.identityHashCode(obj) 的區別

/**
   * 比較obj.hashCode 和系統的  System.identityHashCode(obj)的不一樣
   * obj.hashCode比較的是值,是obj重寫的hashCode方法,
   * System.identityHashCode是將obj的存儲位置轉換成爲hashCode
   */
  @Test
  public void testSystemHashCode() throws CloneNotSupportedException {
    User u1 = new User(1,"jack");
    User u2 = new User(1,"jack");
    Role role = new Role(1,"normal");
    u1.setRole(role);
    u2.setRole(role);
    User u1Clone = (User) u1.clone();//此處爲淺拷貝,user.getRole指向的是同一個內存地址
    System.out.println("System.identityHashCode(u1)=="+System.identityHashCode(u1.getRole()));
    System.out.println("System.identityHashCode(u1Clone)=="+System.identityHashCode(u1Clone.getRole()));
    System.out.println("System.identityHashCode(u2)=="+System.identityHashCode(u2.getRole()));
    System.out.println("--------------- 分割線 --------------");
    UserOverride u3 = new UserOverride(1, "jack");
    UserOverride u4 = new UserOverride(1, "jack");
    RoleOverride r1 = new RoleOverride(1,"normal");
    u3.setRoleOverride(r1);
    u4.setRoleOverride(r1);
    //此處是深克隆,u3.getRoleOverride是指向不一樣的物理地址
    UserOverride u3Clone = (UserOverride) u3.clone();
    System.out.println("System.identityHashCode(u3)=="+System.identityHashCode(u3.getRoleOverride()));
    System.out.println("System.identityHashCode(u3Clone)=="+System.identityHashCode(u3Clone.getRoleOverride()));
    System.out.println("System.identityHashCode(u4)=="+System.identityHashCode(u4.getRoleOverride()));

    /**
     * 運行結果
     * System.identityHashCode(u1)==1023487453
     * System.identityHashCode(u1Clone)==1023487453
     * System.identityHashCode(u2)==1023487453
     * --------------- 分割線 --------------
     * System.identityHashCode(u3)==1865127310
     * System.identityHashCode(u3Clone)==515132998
     * System.identityHashCode(u4)==1865127310
     */
  }

 

 

 

下面是所有源碼,寫的都是內部類+@Test註解,能夠直接運行

import static java.lang.Thread.sleep;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import org.junit.Test;

public class TestObject {

  @Test
  public void testGetClass() {
    User user = new User();
    Class<? extends User> userClass = user.getClass();
    System.out.println(userClass.getName());
    System.out.println(userClass.getSimpleName());
    System.out.println(userClass.getTypeName());
    /**
     * ....能夠獲取更多信息
     * 執行結果
     * com.daly.demo.test.TestObject$User
     * User
     * com.daly.demo.test.TestObject$User
     */
  }

  @Test
  public void testHashCode() {
    User user1 = new User(1, "jack");
    User user2 = new User(1, "jack");
    HashSet<User> set = new HashSet<>();
    set.add(user1);
    set.add(user2);
    System.out.println("user1.hashcode =" + user1.hashCode());
    System.out.println("user2.hashcode =" + user2.hashCode());
    System.out.println("uesr1.equals(user2) is " + user1.equals(user2));
    System.out.println("set.size = " + set.size());
    /**
     * 在使用HashMap,HashSet時,經過比較hahscode的值來判斷是否相等
     * 運行結果
     * user1.hashcode =1023487453
     * user2.hashcode =1865127310
     * uesr1.equals(user2) is false
     * set.size = 2
     */
  }

  @Test
  public void testHashCodeOverride() {
    UserOverride user1 = new UserOverride(1, "jack");
    UserOverride user2 = new UserOverride(1, "jack");
    HashSet<UserOverride> set = new HashSet<>();
    set.add(user1);
    set.add(user2);
    System.out.println("user1.hashcode =" + user1.hashCode());
    System.out.println("user2.hashcode =" + user2.hashCode());
    System.out.println("uesr1.equals(user2) is " + user1.equals(user2));
    System.out.println("set.size =" + set.size());
    /**
     * 在使用HashMap,HashSet時,經過比較hahscode的值來判斷是否相等
     * 運行結果
     * user1.hashcode =3254238
     * user2.hashcode =3254238
     * uesr1.equals(user2) is true
     * set.size =1
     */
  }


  @Test
  public void testEquals() {
    int i1 = 127, i2 = 127;
    Integer ibox1 = 128, ibox2 = 128;
    System.out
        .println("int i1 = 127,i2 = 127;            --> i1 == i2            is " + (i1 == i2));
    System.out.println(
        "Integer ibox1 = 128, ibox2 = 128; --> ibox1 == ibox2      is " + (ibox1 == ibox2));
    System.out.println(
        "Integer ibox1 = 128, ibox2 = 128; --> ibox1.equals(ibox2) is " + ibox1.equals(ibox2));
    /**
     * 由於Integer在重寫equals方法時,
     * 執行結果
     * int i1 = 127,i2 = 127;            --> i1 == i2            is true
     * Integer ibox1 = 128, ibox2 = 128; --> ibox1 == ibox2      is false
     * Integer ibox1 = 128, ibox2 = 128; --> ibox1.equals(ibox2) is true
     */
  }

  @Test
  public void testCloneShallow() throws CloneNotSupportedException {
    Role role = new Role(1, "normal");
    User user = new User(1, "jack");
    user.setRole(role);
    User userClone;
    userClone = (User) user.clone();
    System.out.println("user.equals(userClone)                 is " + user.equals(userClone));
    System.out.println("user == userClone                      is " + (user == userClone));
    System.out.println(
        "user.getRole() == userClone.getRole() is " + (user.getRole() == userClone.getRole()));
    System.out.println("------------ 分割線 -----------");
    user.getRole().setRoleName(user.getRole().getRoleName().toUpperCase());
    System.out.println("user.getRole().getRoleName()      is " + user.getRole().getRoleName());
    System.out.println("userClone.getRole().getRoleName() is " + userClone.getRole().getRoleName());
    /**
     * 此處的user.clone()爲淺拷貝,因此user和userClone的UserOverride是指向同一內存地址的對象
     * 執行結果
     * 由於User沒有重寫equals方法,因此 equals的結果跟== 都爲false
     * user.equals(userClone)                 is false
     * user == userClone                      is false
     * user.getRole() == userClone.getRole() is true
     * ------------ 分割線 -----------
     * user.getRole().getRoleName()      is NORMAL
     * userClone.getRole().getRoleName() is NORMAL
     */
  }

  @Test
  public void testCloneDeep() throws CloneNotSupportedException {
    RoleOverride role = new RoleOverride(1, "normal");
    UserOverride user = new UserOverride(1, "jack");
    user.setRoleOverride(role);
    UserOverride userClone;
    userClone = (UserOverride) user.clone();
    System.out.println("user.equals(userClone)  is " + user.equals(userClone));
    System.out.println("user == userClone       is " + (user == userClone));
    System.out.println("they'er getUserOverride is " +
        (user.getRoleOverride() == userClone.getRoleOverride()));
    System.out.println("------------ 分割線 -----------");
    user.getRoleOverride().setRoleName(user.getRoleOverride().getRoleName().toUpperCase());
    System.out.println("user.getRole().getRoleName() is " + user.getRoleOverride().getRoleName());
    System.out.println(
        "userClone.getRole().getRoleName() is " + userClone.getRoleOverride().getRoleName());
    /**
     * 此處的user.clone()爲淺拷貝,因此user和userClone的UserOverride是指向同一內存地址的對象
     * 執行結果
     * 由於 RoleOverride 重寫了equals方法,因此 equals的結果爲true, == 結果爲 false
     * user.equals(userClone)  is true
     * user == userClone       is false
     * they'er getUserOverride is false
     * ------------ 分割線 -----------
     * user.getRole().getRoleName() is NORMAL
     * userClone.getRole().getRoleName() is normal
     */
  }

  /**
   * 來自博客 https://blog.csdn.net/u014658905/article/details/81035870
   */
  @Test
  public void testNotifyAll() throws InterruptedException {
    final NotificationTest test = new NotificationTest();
    Runnable waitTask = () -> {
      try {
        test.shouldGo();
      } catch (InterruptedException ex) {
        System.out.println(ex.getMessage());
      }
      System.out.println(Thread.currentThread().getName() + " finished Execution");
    };
    Runnable notifyTask = () -> {
      test.go();
      System.out.println(Thread.currentThread().getName() + " finished Execution");
    };
    Thread t1 = new Thread(waitTask, "WT1"); //will wait
    Thread t2 = new Thread(waitTask, "WT2"); //will wait
    Thread t3 = new Thread(waitTask, "WT3"); //will wait
    Thread t4 = new Thread(notifyTask, "NT1"); //will notify
    //starting all waiting thread
    t1.start();
    t2.start();
    t3.start();
    //pause to ensure all waiting thread started successfully
    sleep(200);
    //starting notifying thread
    t4.start();
    /**
     * 運行結果
     * WT1 is going to wait on this object
     * WT2 is going to wait on this object
     * WT3 is going to wait on this object
     * NT1 is going to notify all or one thread waiting on this object
     * NT1 finished Execution
     * WT3 is woken up
     * WT3 finished Execution
     * WT2 is woken up
     * WT2 is going to wait on this object
     * WT1 is woken up
     * WT1 is going to wait on this object
     */
  }

  /**
   * 來自博客 https://blog.csdn.net/u014658905/article/details/81035870
   */
  @Test
  public void testNotify() throws InterruptedException {
    final NotificationTest test = new NotificationTest();
    Runnable waitTask = () -> {
      try {
        test.shouldGo();
      } catch (InterruptedException ex) {
        System.out.println(ex.getMessage());
      }
      System.out.println(Thread.currentThread().getName() + " finished Execution");
    };
    Runnable notifyTask = () -> {
      test.go2();
      System.out.println(Thread.currentThread().getName() + " finished Execution");
    };
    Thread t1 = new Thread(waitTask, "WT1"); //will wait
    Thread t2 = new Thread(waitTask, "WT2"); //will wait
    Thread t3 = new Thread(waitTask, "WT3"); //will wait
    Thread t4 = new Thread(notifyTask, "NT1"); //will notify
    //starting all waiting thread
    t1.start();
    t2.start();
    t3.start();
    //pause to ensure all waiting thread started successfully
    sleep(200);
    //starting notifying thread
    t4.start();
    /**
     * 運行結果
     * WT1 is going to wait on this object
     * WT2 is going to wait on this object
     * WT3 is going to wait on this object
     * NT1 is going to notify all or one thread waiting on this object
     * NT1 finished Execution
     * WT1 is woken up
     * WT1 finished Execution
     */
  }

  /**
   * 除了耗時完成後自動喚醒,還能夠被notify和notifyAll喚醒 notify和notifyAll喚醒方式,如上面的例子所示
   */
  @Test
  public void testWait() throws InterruptedException {
    Runnable myThread = () -> {
      synchronized (this) {
        try {
          System.out
              .println("myThread start at " + new SimpleDateFormat("mm:ss").format(new Date()));
          //wait(5000);//5秒鐘以後喚醒當前線程.繼續執行
          wait();//一直等待
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println("myThread run end");
      }
    };

    Thread t1 = new Thread(myThread, "t1"); //will wait
    synchronized (t1) {
      t1.start();
      t1.wait(2000); //2秒鐘以後,喚醒了main線程繼續執行
      //t1.wait(2000,1000);//1000000*2000+1000 毫微秒鐘以後,喚醒了main線程,徹底體現不出來這第二個參數的意義
      //t1.wait();//mian線程一直等待,沒有被其餘線程喚醒
      System.out
          .println("mainThread wake up at " + new SimpleDateFormat("mm:ss").format(new Date()));
      System.out.println("main run end");
    }
    /**
     * 運行結果以下
     * 當myThread被提早喚醒時,後面的代碼不會被執行
     * myThread start at 38:57
     * myThread run end
     * mainThread wake up at 39:02
     * main run end
     * 或
     *myThread start at 41:52
     * mainThread wake up at 41:54
     * main run end
     */
  }


  /**
   * 很經典的GC回收機制實例
   */
  @Test
  public void testFinalize() throws InterruptedException {
    // 新建對象,由於SAVE_HOOK指向這個對象,對象此時的狀態是(reachable,unfinalized)
    GC.SAVE_HOOK = new GC();
    //將SAVE_HOOK設置成null,此時剛纔建立的對象就不可達了,由於沒有句柄再指向它了,對象此時狀態是(unreachable,unfinalized)
    GC.SAVE_HOOK = null;
    //強制系統執行垃圾回收,系統發現剛纔建立的對象處於unreachable狀態,並檢測到這個對象的類覆蓋了finalize方法,所以把這個對象放入F-Queue隊列,由低優先級線程執行它的finalize方法,此時對象的狀態變成(unreachable, finalizable)或者是(finalizer-reachable,finalizable)
    System.gc();
    // sleep,目的是給低優先級線程從F-Queue隊列取出對象並執行其finalize方法提供機會。在執行完對象的finalize方法中的super.finalize()時,對象的狀態變成(unreachable,finalized)狀態,但接下來在finalize方法中又執行了SAVE_HOOK = this;這句話,又有句柄指向這個對象了,對象又可達了。所以對象的狀態又變成了(reachable, finalized)狀態。
    Thread.sleep(500);
    // 這裏樓主說對象處於(reachable,finalized)狀態應該是合理的。對象的finalized方法被執行了,所以是finalized狀態。又由於在finalize方法是執行了SAVE_HOOK=this這句話,原本是unreachable的對象,又變成reachable了。
    if (null != GC.SAVE_HOOK) { //此時對象應該處於(reachable, finalized)狀態
      // 這句話會輸出,注意對象由unreachable,通過finalize復活了。
      System.out.println("Yes , I am still alive");
    } else {
      System.out.println("No , I am dead");
    }
    // 再一次將SAVE_HOOK放空,此時剛纔復活的對象,狀態變成(unreachable,finalized)
    GC.SAVE_HOOK = null;
    // 再一次強制系統回收垃圾,此時系統發現對象不可達,雖然覆蓋了finalize方法,但已經執行過了,所以直接回收。
    System.gc();
    // 爲系統回收垃圾提供機會
    Thread.sleep(500);
    if (null != GC.SAVE_HOOK) {
      // 這句話不會輸出,由於對象已經完全消失了。
      System.out.println("Yes , I am still alive");
    } else {
      System.out.println("No , I am dead");
    }
  }
 /**
   * 比較obj.hashCode 和系統的  System.identityHashCode(obj)的不一樣
   * obj.hashCode比較的是值,是obj重寫的hashCode方法,
   * System.identityHashCode是將obj的存儲位置轉換成爲hashCode
   */
  @Test
  public void testSystemHashCode() throws CloneNotSupportedException {
    User u1 = new User(1,"jack");
    User u2 = new User(1,"jack");
    Role role = new Role(1,"normal");
    u1.setRole(role);
    u2.setRole(role);
    User u1Clone = (User) u1.clone();//此處爲淺拷貝,user.getRole指向的是同一個內存地址
    System.out.println("System.identityHashCode(u1)=="+System.identityHashCode(u1.getRole()));
    System.out.println("System.identityHashCode(u1Clone)=="+System.identityHashCode(u1Clone.getRole()));
    System.out.println("System.identityHashCode(u2)=="+System.identityHashCode(u2.getRole()));
    System.out.println("--------------- 分割線 --------------");
    UserOverride u3 = new UserOverride(1, "jack");
    UserOverride u4 = new UserOverride(1, "jack");
    RoleOverride r1 = new RoleOverride(1,"normal");
    u3.setRoleOverride(r1);
    u4.setRoleOverride(r1);
    //此處是深克隆,u3.getRoleOverride是指向不一樣的物理地址
    UserOverride u3Clone = (UserOverride) u3.clone();
    System.out.println("System.identityHashCode(u3)=="+System.identityHashCode(u3.getRoleOverride()));
    System.out.println("System.identityHashCode(u3Clone)=="+System.identityHashCode(u3Clone.getRoleOverride()));
    System.out.println("System.identityHashCode(u4)=="+System.identityHashCode(u4.getRoleOverride()));

    /**
     * 運行結果
     * System.identityHashCode(u1)==1023487453
     * System.identityHashCode(u1Clone)==1023487453
     * System.identityHashCode(u2)==1023487453
     * --------------- 分割線 --------------
     * System.identityHashCode(u3)==1865127310
     * System.identityHashCode(u3Clone)==515132998
     * System.identityHashCode(u4)==1865127310
     */
  }

  private class User implements Cloneable {

    private int userId;
    private String userName;
    private Role role;

    User() {
    }

    User(int userId, String userName) {
      this.userId = userId;
      this.userName = userName;
    }

    Role getRole() {
      return role;
    }

    void setRole(Role role) {
      this.role = role;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
      return super.clone();
    }
  }

  private class UserOverride implements Cloneable {

    private int userId;
    private String userName;
    private RoleOverride roleOverride;

    UserOverride(int userId, String userName) {
      this.userId = userId;
      this.userName = userName;
    }

    RoleOverride getRoleOverride() {
      return roleOverride;
    }

    void setRoleOverride(RoleOverride roleOverride) {
      this.roleOverride = roleOverride;
    }

    @Override
    public int hashCode() {
      return userName.hashCode() ^ userId;
    }

    @Override
    public boolean equals(Object obj) {
      if (obj == null) {
        return false;
      }
      //若是是同一個對象返回true,反之返回false
      if (this == obj) {
        return true;
      }
      //判斷是否類型相同
      if (this.getClass() != obj.getClass()) {
        return false;
      }
      UserOverride person = (UserOverride) obj;
      return userName.equals(person.userName) && userId == person.userId;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
      Object clone = super.clone();
      RoleOverride roleOverride = ((UserOverride) clone).getRoleOverride();
      ((UserOverride) clone).setRoleOverride((RoleOverride) roleOverride.clone());
      return clone;
    }
  }

  private class Role {

    private int roleId;
    private String roleName;

    Role(int roleId, String roleName) {
      this.roleId = roleId;
      this.roleName = roleName;
    }

    String getRoleName() {
      return roleName;
    }

    void setRoleName(String roleName) {
      this.roleName = roleName;
    }
  }

  private class RoleOverride implements Cloneable {

    private int roleId;
    private String roleName;

    RoleOverride(int roleId, String roleName) {
      this.roleId = roleId;
      this.roleName = roleName;
    }

    String getRoleName() {
      return roleName;
    }

    void setRoleName(String roleName) {
      this.roleName = roleName;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
      return super.clone();
    }
  }

  private class NotificationTest {

    private volatile boolean go = false;

    synchronized void shouldGo() throws InterruptedException {
      while (go != true) {
        System.out.println(Thread.currentThread().getName()
            + " is going to wait on this object");
        wait(); //release lock and reacquires on wakeup
        System.out.println(Thread.currentThread().getName() + " is woken up");
      }
      go = false; //resetting condition
    }

    /*
     * both shouldGo() and go() are locked on current object referenced by "this" keyword
     */
    synchronized void go() {
      while (go == false) {
        System.out.println(Thread.currentThread().getName()
            + " is going to notify all or one thread waiting on this object");

        go = true; //making condition true for waiting thread
        //notify(); // only one out of three waiting thread WT1, WT2,WT3 will woke up
        notifyAll(); // all waiting thread  WT1, WT2,WT3 will woke up
      }

    }

    synchronized void go2() {
      while (go == false) {
        System.out.println(Thread.currentThread().getName()
            + " is going to notify all or one thread waiting on this object");

        go = true; //making condition true for waiting thread
        notify(); // only one out of three waiting thread WT1, WT2,WT3 will woke up
        //notifyAll(); // all waiting thread  WT1, WT2,WT3 will woke up
      }

    }
  }

  private static class GC {

    static GC SAVE_HOOK = null;

    @Override
    protected void finalize() throws Throwable {
      super.finalize();
      System.out.println("execute method finalize()");
      // 這句話讓對象的狀態由unreachable變成reachable,就是對象復活
      SAVE_HOOK = this;
    }
  }

}

下一章節傳送門 --> jdk8源碼分析筆記1 --> Object.class

相關文章
相關標籤/搜索