Object中(zhong)有(you)哪(na)些公(gong)共(gong)方法及作用
時間:2019-05-27 來源:華(hua)清遠見(jian)
大家在學習java的時(shi)候,一定遇到過Object類,因為在java單一繼承體(ti)系(xi)中Object類是根類,所有(you)的類都會繼承它,并擁有(you)Object的公(gong)共方法,意(yi)味著在java的面向(xiang)對象的世界(jie)中,所有(you)對象都擁有(you)這些方法,非常通用。那么(me)我們來看(kan)一看(kan)這些方法有(you)哪些?
直(zhi)接看一下,Object類的(de)源碼:
package java.lang;
public class Object {
private static native void registerNatives();
static {
registerNatives();
}
public final native Class<?> getClass();
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
protected native Object clone() throws CloneNotSupportedException;
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
public final native void notify();
public final native void notifyAll();
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException {
if (timeout < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && timeout == 0)) {
timeout++;
}
wait(timeout);
}
public final void wait() throws InterruptedException {
wait(0);
}
protected void finalize() throws Throwable { }
}
其實看(kan)JDK文檔大家都能知道這些方(fang)(fang)法(fa)(fa)的含(han)義(yi),不(bu)過我(wo)把自己對它(ta)們(men)的理解介(jie)紹一(yi)下,這里面public的方(fang)(fang)法(fa)(fa),重(zhong)點我(wo)會詳細介(jie)紹較難掌(zhang)握的wait和(he)notify方(fang)(fang)法(fa)(fa)。
具體方法的說明如下:
public String toString()
這個默認是打印對象的getClass().getName() + '@' + Integer.toHexString(hashCode())
類名@哈希碼,可子(zi)類可重寫該方法定義自己的對象字符串,最(zui)常用(yong)。
public final native Class<?> getClass();
獲取對象的類名,在反射中可以(yi)用到(dao)。
public int hashCode();
public boolean equals(Object obj)
這(zhe)兩個方(fang)法在(zai)集合框(kuang)架(jia)的(de)(de)Set集合類中用途非(fei)常重(zhong)要(yao),因(yin)為Set集合中的(de)(de)元素(su)不允許重(zhong)復,各種(zhong)自定(ding)義對象(xiang)如何判斷(duan)是否重(zhong)復,就是通(tong)過重(zhong)寫這(zhe)兩個方(fang)法來完成的(de)(de)。
public final native void notify();
public final native void notifyAll();
public final void wait()
public final native void wait(long timeout)
public final void wait(long timeout, int nanos)
這里幾組(zu)方法(fa)(fa)有多個重載方法(fa)(fa),不過核心的(de)方法(fa)(fa)就是wait方法(fa)(fa)和notify方法(fa)(fa),這兩個方法(fa)(fa),如果沒有學習(xi)過java多線程(cheng)編程(cheng)估計不會接觸(chu)到,這涉及到線程(cheng)的(de)同步以及在同步條件下線程(cheng)通信的(de)問(wen)題(ti)。
java 線程(cheng)同步(bu)機制就是保證多個(ge)(ge)線程(cheng)訪問(wen)同一(yi)個(ge)(ge)共享對象時不發生沖(chong)突的步(bu)驟是上(shang)鎖、操作、釋放鎖。而這個(ge)(ge)鎖是在java對象中(zhong)隱含的鎖,鎖也(ye)叫"同步(bu)監視器" ,它是所有(you)對象都擁(yong)有(you)的,你不用可(ke)視而不見,
其(qi)實(shi)就(jiu)定義在Object類(lei)中(zhong),不(bu)過我們不(bu)用了(le)解(jie)它的存在,為(wei)了(le)防止(zhi)同(tong)一個(ge)(ge)共(gong)享對(dui)(dui)象不(bu)發生沖突,java用 synchronized 來保護(hu)共(gong)享對(dui)(dui)象不(bu)處于競爭狀態.,可(ke)(ke)采(cai)用同(tong)步方(fang)(fang)法或同(tong)步塊來完成,但(dan)是當同(tong)步環境(jing)下(xia)兩個(ge)(ge)線程(cheng)需要通信怎么辦?如果沒有通信機(ji)制,兩個(ge)(ge)線程(cheng)只(zhi)能針(zhen)對(dui)(dui)鎖(suo)的獲(huo)取發出輪詢(xun)效率很低,這(zhe)里Object類(lei)的wait和(he)notify兩個(ge)(ge)方(fang)(fang)法就(jiu)可(ke)(ke)以解(jie)決這(zhe)個(ge)(ge)問題(ti)。
采用(yong) wait()/notify() 實現同(tong)步條件(jian)下(xia)線(xian)程間通信的(de)原理如下(xia):
使用前提:必須(xu)是同(tong)步條件,否則調用會(hui)異常.
調用wait()
調用線程會放棄CPU
調(diao)用線(xian)程釋放(fang)鎖(suo)
調用線程進(jin)入鎖的等(deng)待集(ji)合(池),等(deng)待CPU重新(xin)調度(du)。
調用notify()
某個線(xian)程從(cong)鎖的等待集合中(zhong)離開進入準備(bei)運行狀態(tai)
被通知的線程(cheng)必須重新請求鎖才能執行(xing).
notify()不(bu)能(neng)精確指定被(bei)通(tong)知的線程.
notifyAll() 通知所有在等待集(ji)合的(de)線程離開進入準備運行狀態
下面以(yi)經典的生產者(zhe)和消(xiao)費(fei)者(zhe)問題來(lai)了解(jie)生產者(zhe)線(xian)程Producer和消(xiao)費(fei)者(zhe)線(xian)程Consumer,同(tong)步一個同(tong)享對(dui)象Shop,利(li)用(yong)wait和notify方法來(lai)通信的代碼:
Puducer.java 生(sheng)產者線程定義(yi)
public class Producer implements Runnable{
Shop shop;
public Producer(Shop shop) {
// TODO Auto-generated constructor stub
this.shop=shop;
new Thread(this,"生產者線程").start();
}
@Override
public void run() {
// TODO Auto-generated method stub
int i=0;
while(true){
shop.put(i++);
}
}
}
Consumer.java 消(xiao)費者(zhe)線程定(ding)義
public class Consumer implements Runnable{
Shop shop;
public Consumer(Shop shop) {
// TODO Auto-generated constructor stub
this.shop=shop;
new Thread(this,"消(xiao)費者線程").start();
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
shop.get();
}
}
}
共享對象(xiang)Shop.java定義
public class Shop {
int no;
boolean hasData=false; //false表示無數據(ju)(ju) true有數據(ju)(ju)
synchronized int get(){ //消費產品
if(hasData==false){
try {
wait();//消費者(zhe)線程暫停(ting)
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("消費:"+no);
hasData=false;//消費(fei)完了.通知(zhi)生(sheng)產
notify();
return no;
}
synchronized void put(int no){ //放產品
if(hasData==true){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("生產:"+no);
hasData=true;
this.no=no;
notify();
}
}
測試類PC.java
public class PC {
public static void main(String[] args) {
Shop shop=new Shop();
new Producer(shop);
new Consumer(shop);
}
}
以上生產消費者問(wen)題很(hen)好的說明了wait和notify方法的用途,其(qi)他方法的變種例如(ru)wait(long timeout)就好理解(jie)了,如(ru)果超(chao)過(guo)指定時間(jian)等待的線程(cheng)也(ye)會進入(ru)等待集合而不用再(zai)等待。

