【java基礎之jdk源碼】Object

最新在總體迴歸下java基礎薄弱環節,如下爲本身整理筆記,如有理解錯誤,請批評指正,謝謝。java

java.lang.Object爲java全部類的基類,因此通常的類均可用重寫或直接使用Object下方法,如下爲邏輯結構圖,沒有畫類圖c++

(注: 以上綠色方法爲 非native方法  粉色方法爲 native方法)數組

那麼問題來了 :app

一、what is a native object? 

  本人理解: native關鍵字標識的java方法爲本地方法,底層是有c/c++編寫的程序編譯後dll文件,java加載dll文件後,less

        可用經過本地方法調用dll中函數,若有疑問可用參考JNI使用方式,看參考:http://blog.csdn.net/yangjiali014/article/details/1633017dom

        如下爲Object類對應openjdk\jdk\src\share\native\java\lang\Object.c的源碼片斷1jvm

1 static JNINativeMethod methods[] = {
2     {"hashCode",    "()I",                    (void *)&JVM_IHashCode},
3     {"wait",        "(J)V",                   (void *)&JVM_MonitorWait},
4     {"notify",      "()V",                    (void *)&JVM_MonitorNotify},
5     {"notifyAll",   "()V",                    (void *)&JVM_MonitorNotifyAll},
6     {"clone",       "()Ljava/lang/Object;",   (void *)&JVM_Clone},
7 };

  網友看法:http://stackoverflow.com/questions/4568972/what-is-a-native-objectasync

二、Why exist native method in Object Class?

  本人理解:涉及調用系統及考慮性能,使用c++或c實現更佳ide

  網友看法:http://stackoverflow.com/questions/10578764/why-are-hashcode-and-getclass-native-methods函數

       http://stackoverflow.com/questions/27224577/why-is-object-clone-native-in-java

  

如今按上圖逐個方法講講理解:

  一、Object():默認構造函數

  二、 registerNatives(): 用於註冊 代碼片斷1中的本地方法到jvm中

  java代碼 片斷2

1  private static native void registerNatives();
2  static {
3      registerNatives();
4  }

  對應c++代碼 片斷3

1 JNIEXPORT void JNICALL
2 Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls)
3 {
4     (*env)->RegisterNatives(env, cls,
5                             methods, sizeof(methods)/sizeof(methods[0]));
6 }

  三、final getClass():  (不能重寫方法)方法說明中已經提示:Returns:The Class object that represents the runtime class of this object.

   來個簡單例子 片斷4

 1 package jdk;
 2 
 3 public class ObjectTest {
 4 
 5     public static void main(String[] args) {
 6         A a = new B();
 7         System.out.println(a.getClass());
 8     }
 9 }
10 
11 class A {
12     static{
13         System.out.println("初始化a");
14     }
15     
16 }
17 
18 class B extends A{
19     static{
20         System.out.println("初始化b");
21     }
22 }

  輸出結果:

  能夠看到getClass返回的爲class B 非 A。

   四、hashCode():返回一個整數的值依賴於內部表示堆上的對象的指針

    方法說明:This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not           required by the Java™ programming language

  一塊兒看下native方法 位於openjdk\hotspot\src\share\vm\prims\jvm.cpp中 JVM_IHashCode的實現 

1 JVM_ENTRY(jint, JVM_IHashCode(JNIEnv* env, jobject handle))
2   JVMWrapper("JVM_IHashCode");
3   // as implemented in the classic virtual machine; return 0 if object is NULL
4   return handle == NULL ? 0 : ObjectSynchronizer::FastHashCode (THREAD, JNIHandles::resolve_non_null(handle)) ;
5 JVM_END

調用了ObjectSynchronizer::FastHashCode方法,位於openjdk\hotspot\src\share\vm\runtime\synchronizer.cpp中 第530行起

  1 static inline intptr_t get_next_hash(Thread * Self, oop obj) {
  2   intptr_t value = 0 ;
  3   if (hashCode == 0) {
  4      // This form uses an unguarded global Park-Miller RNG,
  5      // so it's possible for two threads to race and generate the same RNG.
  6      // On MP system we'll have lots of RW access to a global, so the
  7      // mechanism induces lots of coherency traffic.
  8      value = os::random() ;
  9   } else
 10   if (hashCode == 1) {
 11      // This variation has the property of being stable (idempotent)
 12      // between STW operations.  This can be useful in some of the 1-0
 13      // synchronization schemes.
 14      intptr_t addrBits = intptr_t(obj) >> 3 ;
 15      value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom ;
 16   } else
 17   if (hashCode == 2) {
 18      value = 1 ;            // for sensitivity testing
 19   } else
 20   if (hashCode == 3) {
 21      value = ++GVars.hcSequence ;
 22   } else
 23   if (hashCode == 4) {
 24      value = intptr_t(obj) ;
 25   } else {
 26      // Marsaglia's xor-shift scheme with thread-specific state
 27      // This is probably the best overall implementation -- we'll
 28      // likely make this the default in future releases.
 29      unsigned t = Self->_hashStateX ;
 30      t ^= (t << 11) ;
 31      Self->_hashStateX = Self->_hashStateY ;
 32      Self->_hashStateY = Self->_hashStateZ ;
 33      Self->_hashStateZ = Self->_hashStateW ;
 34      unsigned v = Self->_hashStateW ;
 35      v = (v ^ (v >> 19)) ^ (t ^ (t >> 8)) ;
 36      Self->_hashStateW = v ;
 37      value = v ;
 38   }
 39 
 40   value &= markOopDesc::hash_mask;
 41   if (value == 0) value = 0xBAD ;
 42   assert (value != markOopDesc::no_hash, "invariant") ;
 43   TEVENT (hashCode: GENERATE) ;
 44   return value;
 45 }
 46 //
 47 intptr_t ObjectSynchronizer::FastHashCode (Thread * Self, oop obj) {
 48   if (UseBiasedLocking) {
 49     // NOTE: many places throughout the JVM do not expect a safepoint
 50     // to be taken here, in particular most operations on perm gen
 51     // objects. However, we only ever bias Java instances and all of
 52     // the call sites of identity_hash that might revoke biases have
 53     // been checked to make sure they can handle a safepoint. The
 54     // added check of the bias pattern is to avoid useless calls to
 55     // thread-local storage.
 56     if (obj->mark()->has_bias_pattern()) {
 57       // Box and unbox the raw reference just in case we cause a STW safepoint.
 58       Handle hobj (Self, obj) ;
 59       // Relaxing assertion for bug 6320749.
 60       assert (Universe::verify_in_progress() ||
 61               !SafepointSynchronize::is_at_safepoint(),
 62              "biases should not be seen by VM thread here");
 63       BiasedLocking::revoke_and_rebias(hobj, false, JavaThread::current());
 64       obj = hobj() ;
 65       assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
 66     }
 67   }
 68 
 69   // hashCode() is a heap mutator ...
 70   // Relaxing assertion for bug 6320749.
 71   assert (Universe::verify_in_progress() ||
 72           !SafepointSynchronize::is_at_safepoint(), "invariant") ;
 73   assert (Universe::verify_in_progress() ||
 74           Self->is_Java_thread() , "invariant") ;
 75   assert (Universe::verify_in_progress() ||
 76          ((JavaThread *)Self)->thread_state() != _thread_blocked, "invariant") ;
 77 
 78   ObjectMonitor* monitor = NULL;
 79   markOop temp, test;
 80   intptr_t hash;
 81   markOop mark = ReadStableMark (obj);
 82 
 83   // object should remain ineligible for biased locking
 84   assert (!mark->has_bias_pattern(), "invariant") ;
 85 
 86   if (mark->is_neutral()) {
 87     hash = mark->hash();              // this is a normal header
 88     if (hash) {                       // if it has hash, just return it
 89       return hash;
 90     }
 91     hash = get_next_hash(Self, obj);  // allocate a new hash code
 92     temp = mark->copy_set_hash(hash); // merge the hash code into header
 93     // use (machine word version) atomic operation to install the hash
 94     test = (markOop) Atomic::cmpxchg_ptr(temp, obj->mark_addr(), mark);
 95     if (test == mark) {
 96       return hash;
 97     }
 98     // If atomic operation failed, we must inflate the header
 99     // into heavy weight monitor. We could add more code here
100     // for fast path, but it does not worth the complexity.
101   } else if (mark->has_monitor()) {
102     monitor = mark->monitor();
103     temp = monitor->header();
104     assert (temp->is_neutral(), "invariant") ;
105     hash = temp->hash();
106     if (hash) {
107       return hash;
108     }
109     // Skip to the following code to reduce code size
110   } else if (Self->is_lock_owned((address)mark->locker())) {
111     temp = mark->displaced_mark_helper(); // this is a lightweight monitor owned
112     assert (temp->is_neutral(), "invariant") ;
113     hash = temp->hash();              // by current thread, check if the displaced
114     if (hash) {                       // header contains hash code
115       return hash;
116     }
117     // WARNING:
118     //   The displaced header is strictly immutable.
119     // It can NOT be changed in ANY cases. So we have
120     // to inflate the header into heavyweight monitor
121     // even the current thread owns the lock. The reason
122     // is the BasicLock (stack slot) will be asynchronously
123     // read by other threads during the inflate() function.
124     // Any change to stack may not propagate to other threads
125     // correctly.
126   }
View Code

  該方法通常會被子類重寫,String方法的hashCode方法代碼 片斷5

  計算方法是 s[0]31^(n-1) + s[1]31^(n-2) + … + s[n-1],其中s[0]表示字符串的第一個字符,n表示字符串長度;

 1  public int hashCode() {
 2         int h = hash;
 3         if (h == 0 && value.length > 0) {
 4             char val[] = value;
 5 
 6             for (int i = 0; i < value.length; i++) {
 7                 h = 31 * h + val[i];
 8             }
 9             hash = h;
10         }
11         return h;
12     }

  五、equals():返回 2個對象的內存地址是否相等

  源碼 片斷6

1 public boolean equals(Object obj) {
2         return (this == obj);
3 }

  該方法通常會被子類重寫,String方法的equal方法代碼 片斷7

   先比較String對象內存地址相同,若相同則返回true,不然判斷String對象對應字符的內容是否相等,若相等則返回true

 1 public boolean equals(Object anObject) {
 2         if (this == anObject) {
 3             return true;
 4         }
 5         if (anObject instanceof String) {
 6             String anotherString = (String)anObject;
 7             int n = value.length;
 8             if (n == anotherString.value.length) {
 9                 char v1[] = value;
10                 char v2[] = anotherString.value;
11                 int i = 0;
12                 while (n-- != 0) {
13                     if (v1[i] != v2[i])
14                         return false;
15                     i++;
16                 }
17                 return true;
18             }
19         }
20         return false;
21     }

  六、clone() throws CloneNotSupportedException:返回複製對象

    先看下方法的說明:Note that all arrays are considered to implement the interface Cloneable and that the return type of the clone method of an array     type T[] is T[] where T is any reference or primitive type

    一塊兒看下native方法 位於openjdk\hotspot\src\share\vm\prims\jvm.cpp中 JVM_Clone的實現  片斷8

JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
  JVMWrapper("JVM_Clone");
  Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
  const KlassHandle klass (THREAD, obj->klass());
  JvmtiVMObjectAllocEventCollector oam;

#ifdef ASSERT
  // Just checking that the cloneable flag is set correct
  if (obj->is_javaArray()) {
    guarantee(klass->is_cloneable(), "all arrays are cloneable");
  } else {
    guarantee(obj->is_instance(), "should be instanceOop");
    bool cloneable = klass->is_subtype_of(SystemDictionary::Cloneable_klass());
    guarantee(cloneable == klass->is_cloneable(), "incorrect cloneable flag");
  }
#endif

  // Check if class of obj supports the Cloneable interface.
  // All arrays are considered to be cloneable (See JLS 20.1.5)
  if (!klass->is_cloneable()) {
    ResourceMark rm(THREAD);
    THROW_MSG_0(vmSymbols::java_lang_CloneNotSupportedException(), klass->external_name());
  }

  // Make shallow object copy
  const int size = obj->size();
  oop new_obj = NULL;
  if (obj->is_javaArray()) {
    const int length = ((arrayOop)obj())->length();
    new_obj = CollectedHeap::array_allocate(klass, size, length, CHECK_NULL);
  } else {
    new_obj = CollectedHeap::obj_allocate(klass, size, CHECK_NULL);
  }
  // 4839641 (4840070): We must do an oop-atomic copy, because if another thread
  // is modifying a reference field in the clonee, a non-oop-atomic copy might
  // be suspended in the middle of copying the pointer and end up with parts
  // of two different pointers in the field.  Subsequent dereferences will crash.
  // 4846409: an oop-copy of objects with long or double fields or arrays of same
  // won't copy the longs/doubles atomically in 32-bit vm's, so we copy jlongs instead
  // of oops.  We know objects are aligned on a minimum of an jlong boundary.
  // The same is true of StubRoutines::object_copy and the various oop_copy
  // variants, and of the code generated by the inline_native_clone intrinsic.
  assert(MinObjAlignmentInBytes >= BytesPerLong, "objects misaligned");
  Copy::conjoint_jlongs_atomic((jlong*)obj(), (jlong*)new_obj,
                               (size_t)align_object_size(size) / HeapWordsPerLong);
  // Clear the header
  new_obj->init_mark();

  // Store check (mark entire object and let gc sort it out)
  BarrierSet* bs = Universe::heap()->barrier_set();
  assert(bs->has_write_region_opt(), "Barrier set does not have write_region");
  bs->write_region(MemRegion((HeapWord*)new_obj, size));

  // Caution: this involves a java upcall, so the clone should be
  // "gc-robust" by this stage.
  if (klass->has_finalizer()) {
    assert(obj->is_instance(), "should be instanceOop");
    new_obj = instanceKlass::register_finalizer(instanceOop(new_obj), CHECK_NULL);
  }

  return JNIHandles::make_local(env, oop(new_obj));
JVM_END

  隱含意思:數組類型默承認以直接克隆,而其餘對象實現clone須要先實現Cloneable接口,不然拋出CloneNotSupportedException異常

  問題1:對象的建立有多中方式,相似 new 、getInstance、clone等 clone有什麼好處?

  問題2:對象調用clone方法生成的對象 和 原對象是否還有什麼關聯關係?

  問題3 : 對象clone存在 「淺複製」、「深複製」概念,怎麼區分?

  帶着這3個問題,理解Object clone方法:

    一、通常native方法比java中非native方法執行效率高 ,看示例  片斷9

 1 package jdk;
 2 
 3 import java.util.Calendar;
 4 import java.util.Date;
 5 
 6 public class ObjectCloneTest1 {
 7 
 8     static final int N = 100000;
 9 
10     public static void main(String[] args) {
11 
12         final Date date = new Date();
13 
14         {
15 
16             final long startTime = System.currentTimeMillis();
17             for (int i = 0; i < N; i++) {
18                 Date date2 = (Date) date.clone();
19             }
20 
21             final long endTime = System.currentTimeMillis();
22 
23             System.out.println("clone:" + (endTime - startTime) + "ms");
24         }
25 
26         {
27             final long startTime = System.currentTimeMillis();
28             for (int i = 0; i < N; i++) {
29                 final Calendar cal = Calendar.getInstance();
30                 cal.setTime(date);
31                 final Date date2 = cal.getTime();
32             }
33 
34             final long endTime = System.currentTimeMillis();
35             System.out.println("Calender.setTime:" + (endTime - startTime) + "ms");
36 
37         }
38 
39     }
40 
41 }

  二、clone生成的新對象與原對象的關係,須要區別2個對象建是否存在相同的引用或對應的內存地址是否存在共用狀況,若存在則 該次clone爲 「淺複製」,不然爲「深複製」, 並且Object的clone方法是屬於 「淺複製」,看示例  片斷10

 1 package jdk;
 2 
 3 
 4 public class ObjectCloneTest2 {
 5 
 6     public static void main(String[] args) {
 7         Animal a1 = new Animal(1, "pig");
 8         Animal a2 = (Animal) a1.clone();
 9         System.out.println(a1.getName() == a2.getName() ? "淺複製" : "深複製");
10         
11         System.out.println(a1);
12         a1.setAge(11);
13         a1.setName("big pig");
14         System.out.println(a1.age + ":" + a1.name);
15         
16         System.out.println(a2);
17         System.out.println(a2.age + ":" + a2.name);
18         
19     }
20 
21 }
22 
23 class Animal implements Cloneable{
24     int age;
25     String name;
26 
27     Animal(int age, String name) {
28         this.age = age;
29         this.name = name;
30     }
31 
32     public Animal clone() {
33         Animal o = null;
34 
35         try {
36             o = (Animal) super.clone();
37         } catch (CloneNotSupportedException e) {
38             e.printStackTrace();
39         }
40 
41         return o;
42     }
43 
44     public int getAge() {
45         return age;
46     }
47 
48     public void setAge(int age) {
49         this.age = age;
50     }
51 
52     public String getName() {
53         return name;
54     }
55 
56     public void setName(String name) {
57         this.name = name;
58     }
59 }
View Code

  "深複製"時,須要將共同關聯的引用也複製徹底看示例  片斷11

 

 1 package jdk;
 2 
 3 public class ObjectCloneTest3 {
 4 
 5     public static void main(String[] args) {
 6         Person p1 = new Person(10, "ll", new Race("yellow", "Asia"));
 7         Person p2 = (Person) p1.clone();
 8         System.out.println(p1.getRace() == p2.getRace());
 9         System.out.println(p1.getTestArray() == p2.getTestArray());
10 
11     }
12 
13 }
14 
15 class Person implements Cloneable {
16     int age;
17     String name;
18     Race race;
19     int[] testArray = { 1, 23, 5, 6, 0 };
20 
21     Person(int age, String name, Race race) {
22         this.age = age;
23         this.name = name;
24         this.race = race;
25     }
26 
27     public Person clone() {
28         Person o = null;
29 
30         try {
31             o = (Person) super.clone();
32             o.setRace(this.race.clone());
33             o.setTestArray(testArray.clone());
34         } catch (CloneNotSupportedException e) {
35             e.printStackTrace();
36         }
37 
38         return o;
39     }
40 
41    
42     public int getAge() {
43         return age;
44     }
45 
46     public void setAge(int age) {
47         this.age = age;
48     }
49 
50     public String getName() {
51         return name;
52     }
53 
54     public void setName(String name) {
55         this.name = name;
56     }
57 
58     public Race getRace() {
59         return race;
60     }
61 
62     public void setRace(Race race) {
63         this.race = race;
64     }
65     
66     public void setTestArray(int[] testArray) {
67         this.testArray = testArray;
68     }
69 
70     public int[] getTestArray() {
71         return testArray;
72     }    
73 
74 }
75 
76 class Race implements Cloneable {
77     String color; // 顏色
78     String distribution; // 分佈
79 
80     public Race(String color, String distribution) {
81         super();
82         this.color = color;
83         this.distribution = distribution;
84     }
85 
86     public Race clone() throws CloneNotSupportedException {
87         return (Race) super.clone();
88     }
89 }
View Code

  七、toString():a string representation of the object.

    方法說明:

    The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@',     and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:

 getClass().getName() + '@' + Integer.toHexString(hashCode())

   默認返回對象的名稱及引用地址,但通常被子類重寫用於說明子類相關屬性值描述

  八、final notify() : 不能被重寫,用於喚醒一個在因等待該對象(調用了wait方法)被處於等待狀態(waiting 或 time_wait)的線程,該方法只能同步方法或同步塊中調用

    方法說明:Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be     awakened. The choice is arbitrary and occurs at the discretion of the implementation. A thread waits on an object's monitor by calling one of the wait     methods. 

  九、final notifyAll():不能被重寫,用於喚醒全部在因等待該對象(調用wait方法)被處於等待狀態(waiting或time_waiting)的線程,該方法只能同步方法或同步塊中調用

    方法說明:Wakes up all threads that are waiting on this object's monitor. A thread waits on an object's monitor by calling one of the wait methods. 

  十、final wait(long timeout):不能被重寫,用於在線程調用中,致使當前線程進入等待狀態(time_waiting),timeout單位爲毫秒,該方法只能同步方法或同步塊中調用,超過設置時間後線程從新進入可運行狀態

    方法說明:Note that the wait method, as it places the current thread into the wait set for this object, unlocks only this object; any other objects on     which the current thread may be synchronized remain locked while the thread waits. 

  十一、final wait(long timeout, int nanos):不能被重寫,在jdk1.8中看當,沒有什麼特殊做用相似 wait(long timeout)方法,片斷12

if (nanos >= 500000 || (nanos != 0 && timeout == 0)) {
            timeout++;
 }

  十二、final void wait()::不能被重寫,用於在線程調用中,致使當前線程進入阻塞狀態(waiting),該方法只能同步方法或同步塊中調用,不會自動,片斷13

   方法說明:The specified amount of real time has elapsed, more or less. If timeout is zero, however, then real time is not taken into consideration and the thread simply waits until notified.

1     public final void wait() throws InterruptedException {
2         wait(0);
3     }

   8,9,10,11,12幾個方法通常配套使用,先了解一下JAVA 線程執行模型

  

  詳細看示例 片斷14

1 synchronized (obj) {
2          while (<condition does not hold>)
3              obj.wait(timeout);
4          ... // Perform action appropriate to condition
5 }
 1 package jdk;
 2 
 3 import java.util.concurrent.ExecutorService;
 4 import java.util.concurrent.Executors;
 5 import java.util.concurrent.ThreadFactory;
 6 import java.util.concurrent.atomic.AtomicInteger;
 7 
 8 public class ObjectWaitTest1 {
 9     static Object lock = new Object();
10 
11     public static void main(String[] args) {
12         
13         ExecutorService executeService = Executors.newCachedThreadPool(new MyThreadFactory());
14         for (int i = 0; i < 10; i++) {
15             executeService.submit(() -> {
16                 synchronized (lock) {
17                     try {
18                         System.out.println(Thread.currentThread().getName() + " begin");
19                         lock.wait(1000 * 30); // wiat 30s
20                     } catch (Exception e) {
21                         e.printStackTrace();
22                     }
23         
24                     System.out.println(Thread.currentThread().getName() + " finish");
25                 }
26             });
27         }
28         
29         executeService.shutdown();
30     }
31 
32     
33     static class MyThreadFactory implements ThreadFactory {
34         
35         private final AtomicInteger threadNumber = new AtomicInteger(1);
36         
37         public Thread newThread(Runnable r) {
38           return new Thread(r, "mythiread - " + threadNumber.getAndIncrement());
39         }
40       }
41 }
View Code

  執行wait過程當中堆棧信息:

  再來個生產消費者的示例 片斷15

 1 package jdk;
 2 
 3 import java.util.LinkedList;
 4 import java.util.Queue;
 5 import java.util.Random;
 6 
 7 public class ObjectWaitTest2 {
 8     static Object lock = new Object();
 9 
10     public static void main(String[] args) {
11         int maxSize = 10;
12         Queue<Integer> buffer = new LinkedList<>();
13 
14         Thread producer = new Producer(buffer, maxSize, "Producer");
15         Thread comsuner = new Comsumer(buffer, maxSize, "comsuner");
16         producer.start();
17         comsuner.start();
18     }
19 
20 }
21 
22 class Producer extends Thread {
23     private Queue<Integer> queue;
24     private int maxSize;
25 
26 
27     public Producer(Queue<Integer> queue, int maxSize, String name) {
28         super(name);
29         this.maxSize = maxSize;
30         this.queue = queue;
31     }
32 
33     @Override
34     public void run() {
35         while (true) {
36 
37             synchronized (queue) {
38                 if (queue.size() == maxSize) {
39                     try {
40                         System.out.println("Queue is full, Producer wair for Comsumer to task something from queue");
41                         queue.wait();
42                     } catch (InterruptedException e) {
43                         e.printStackTrace();
44                     }
45                 }
46                 Random r = new Random();
47                 int value = r.nextInt();
48                 queue.add(value);
49                 System.out.println("Producer value : " + value);
50                 queue.notifyAll();
51             }
52         }
53     }
54 
55 }
56 
57 class Comsumer extends Thread {
58     private Queue<Integer> queue;
59     private int maxSize;
60 
61     public Comsumer(Queue<Integer> queue, int maxSize, String name) {
62         super(name);
63         this.maxSize = maxSize;
64         this.queue = queue;
65     }
66 
67     @Override
68     public void run() {
69         while (true) {
70 
71             synchronized (queue) {
72                 if (queue.isEmpty()) {
73                     try {
74                         System.out.println("Queue is enpty, Comsumer wair for Producer to put something in queue");
75                         queue.wait();
76                     } catch (InterruptedException e) {
77                         e.printStackTrace();
78                     }
79                 }
80                 System.out.println("Comsumer value : " + queue.remove());
81                 queue.notifyAll();
82             }
83         }
84     }
85 
86 }
View Code

 

 1三、finalize():Object的protected方法,子類能夠覆蓋該方法以實現資源清理工做,GC在回收對象以前調用該方法

    方法說明:Called by the garbage collector on an object when garbage collection determines that there are no more references to the object. A     subclass overrides the finalize method to dispose of system resources or to perform other cleanup. 

,該方法只能同步方法或同步塊中調用

相關文章
相關標籤/搜索