咱们在学习java的时分,必定遇到过Object类,由于在java单一承继系统中Object类是根类,一切的类都会承继它,并具有Object的公共办法,意味着在java的面向目标的国际中,一切目标都具有这些办法,十分通用。那么咱们来看一看这些办法有哪些?
直接看一下,Object类的源码:
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 { }
}
其实看JDK文档咱们都能知道这些办法的意义,不过我把自己对它们的了解介绍一下,这儿边public的办法,要点我会具体介绍较难把握的wait和notify办法。
具体办法的阐明如下:
public String toString()
这个默许是打印目标的getClass().getName() + ‘@’ + Integer.toHexString(hashCode())
类名@哈希码,可子类可重写该办法界说自己的目标字符串,最常用。
public final native Class《?》 getClass();
获取目标的类名,在反射中能够用到。
public int hashCode();
public boolean equals(Object obj)
这两个办法在调集结构的Set调集类中用处十分重要,由于Set调集中的元素不允许重复,各种自界说目标怎么判别是否重复,便是经过重写这两个办法来完结的。
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)
这儿几组办法有多个重载办法,不过中心的办法便是wait办法和notify办法,这两个办法,假如没有学习过java多线程编程估量不会接触到,这涉及到线程的同步以及在同步条件下线程通讯的问题。
java 线程同步机制便是确保多个线程拜访同一个同享目标时不发生抵触的过程是上锁、操作、开释锁。而这个锁是在java目标中隐含的锁,锁也叫“同步监视器” ,它是一切目标都具有的,你不必可视若无睹,
其实就界说在Object类中,不过咱们不必了解它的存在,为了避免同一个同享目标不发生抵触,java用 synchronized 来维护同享目标不处于竞赛状况。,可选用同步办法或同步块来完结,可是当同步环境下两个线程需求通讯怎么办?假如没有通讯机制,两个线程只能针对锁的获取宣布轮询功率很低,这儿Object类的wait和notify两个办法就能够处理这个问题。
选用 wait()/notify() 完成同步条件下线程间通讯的原理如下:
运用条件:有必要是同步条件,不然调用会反常。
调用wait()
调用线程会抛弃CPU
调用线程开释锁
调用线程进入锁的等候调集(池),等候CPU从头调度。
调用notify()
某个线程从锁的等候调集中脱离进入预备运转状况
被告诉的线程有必要从头恳求锁才干履行。
notify()不能准确指定被告诉的线程。
notifyAll() 告诉一切在等候调集的线程脱离进入预备运转状况
下面以经典的出产者和顾客问题来了解出产者线程Producer和顾客线程Consumer,同步一个同享目标Shop,使用wait和notify办法来通讯的代码:
Puducer.java 出产者线程界说
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 顾客线程界说
public class Consumer implements Runnable{
Shop shop;
public Consumer(Shop shop) {
// TODO Auto-generated constructor stub
this.shop=shop;
new Thread(this,“顾客线程”).start();
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
shop.get();
}
}
}
同享目标Shop.java界说
public class Shop {
int no;
boolean hasData=false; //false表明无数据 true有数据
synchronized int get(){ //消费产品
if(hasData==false){
try {
wait();//顾客线程暂停
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(“消费:”+no);
hasData=false;//消费完了。告诉出产
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);
}
}
以上出产顾客问题很好的阐明晰wait和notify办法的用处,其他办法的变种例如wait(long timeout)就好了解了,假如超越指定时刻等候的线程也会进入等候调集而不必再等候。
责任编辑:ct