看Java API的Object類, 一共11個方法。按使用的頻度排名:
-
toString()
這個方法最常用在打日誌,定位代碼問題。 equals()
和hashCode()
, 這兩個方法的使用經典例子是HashMap的源碼
public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
if (key == null)
return putForNullKey(value);
int hash = hash(key);
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
equals()
比 hashCode()
要常用一點。
wait()
和notify()
這個開發很少會直接用到,但是間接用到的場景不少,屬於偏內功的點。wait/notify
屬於Object類最難理解的點了,因爲它的基石是多線程。學習思路還是三步走。
step 1: 看文檔說明
wait()
Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.
notify()
Wakes up a single thread that is waiting on this object's monitor.
這個文檔說明,看完基本一頭霧水,兩個方法都提到了如下的核心概念thread
, object's monitor
。 先把這些概念放一邊,看看是怎麼用的。
step 2: 運行Demo
給個demo輔助理解,一個線程是幹活的,另一個線程是管事的。管事的等活幹完驗收。
public class WaitNotifyDemo {
static class Worker extends Thread{
private volatile int status=0; // 1: 完成, -1: 出錯
@Override
public void run(){
try {
System.out.println(Thread.currentThread().getName() +": 開始幹活");
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName() +": 完成任務");
status = 1;
// 通知主線程
synchronized (this){
this.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
status = -1;
}
}
public int getStatus(){
return status;
}
}
public static void main(String[] args) throws InterruptedException {
Worker worker= new Worker();
worker.start();
synchronized (worker){
int status;
while ((status=worker.getStatus())!=1){
worker.wait();
if(status==-1)
throw new RuntimeException("出錯了");
}
}
System.out.println("任務已經完成");
}
}
step3: 折騰demo
接下來, 我試了一下, 把notify的代碼去掉,也能正常運行。 這就讓人困惑了,文檔明明說必須調用notify,wait才能結束
。接下來再看文檔:
A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup
所以, wait方法必須在while循環中調用。好,解答了一點疑惑。但是每次Worker線程結束時沒有調用notify,主線程就能正常退出, 這個也說不通。 唯一的解釋是: JVM內部在某個地方調用了notify。看openjdk的源碼, 果然如此:從start0開始, 定位到線程在退出時會調用lock.notify_all(thread);
。只是這裏的代碼是JVM內部的代碼,比較底層。
其實,這個例子更簡潔的寫法是worker.join()
。 如果看Thread.join()的源碼,發現它的實現恰好就是調用了wait。
-
clone() 這個需要理解深度克隆, 知識點不復雜。
-
getclass() 這個放在後面,但是用得還挺多的,特別是寫框架。
- finalize() 這個已經不他推薦使用了, 儘量不干擾GC的節奏。
總結一下,Object類是Java的基石。這裏比較難一點的就是wait/notify. 學習Java的API, 如果想理解透徹一點,估計繞不開JVM的c++源碼。