sleep与wait方法

1.wait 属性Object类 

(1)首先,调用了wait()之后会引起当前线程处于等待状状态。

(2)其次,每个线程必须持有该对象的monitor。如果在当前线程中调用wait()方法之后,该线程就会释放monitor的持有对象并让自己处于等待状态。

(3)如果想唤醒一个正在等待的线程,那么需要开启一个线程通过notify()或者notifyAll()方法去通知正在等待的线程获取monitor对象。如此,该线程即可打破等待的状态继续执行代码。

sleep属于 Thread 类

(1)首先,调用sleep()之后,会引起当前执行的线程进入暂时中断状态,也即睡眠状态。

(2)其次,虽然当前线程进入了睡眠状态,但是依然持有monitor对象。

(3)在中断完成之后,自动进入唤醒状态从而继续执行代码。

2 .首先写个demo  来看

public class SleepTest {

public static void main(String[] args) {
ThreadOne one = new ThreadOne();
ThreadTwo two = new ThreadTwo();
one.start();
two.start();
}

}class ThreadOne extends Thread{

public void run(){
 

System.out.println("进入了sleep方法当前时间是"+new Date().toLocaleString());
sleep(1000);
System.out.println("sleep方法结束当前时间是"+new Date().toLocaleString());

} catch ( 

class ThreadTwo extends Thread{
public void run(){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}

运行结果:

进入了sleep方法当前时间是2018-7-26 11:24:50
sleep方法结束当前时间是2018-7-26 11:24:51

Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at com.zz.www.Thread.ThreadTwo.run(SleepTest.java:30)

可以看出  sleep方法用法比较简单  但是 wait 方法 必须在synchronized 方法内使用;

修改一下ThreadTwo 

class ThreadTwo extends Thread{

public void run(){
gogo();
}

public synchronized void gogo(){
try {
System.out.println("进入了wait方法 当前时间是"+new Date().toLocaleString());
this.wait(10000);//当前线程等待10000毫秒
System.out.println("wait方法结束 当前时间是"+new Date().toLocaleString());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

再次运行结果为

进入了wait方法 当前时间是2018-7-26 11:25:50
进入了sleep方法当前时间是2018-7-26 11:25:50
sleep方法结束当前时间是2018-7-26 11:25:51
wait方法结束 当前时间是2018-7-26 11:26:00

 

3.  notify(), notifyAll(),wait(), wait(long), wait(long, int)操作,都需要锁对象

例如 :
exapmle 1,锁定方法所属的实例对象:
public synchronized void method(){
    //然后就可以调用:this.notify()...
    //或者直接调用notify()...
}
exapmle 2,锁定方法所属的实例的Class:
public Class Test{
 public static synchronized void method(){
    //然后调用:Test.class.notify()...
 }
}
exapmle 3,锁定其他对象:
public Class Test{
public Object lock = new Object();
 public static void method(){
    synchronized (lock) {
     //需要调用 lock.notify();
    } 
 }
}

 4 测试 wait  与 notify 

public class SleepTest {
private final static Object obj = new Object();
public static void main(String[] args) {
// ThreadOne one = new ThreadOne();
// ThreadTwo two = new ThreadTwo();
// one.start();
// two.start();

Thread thread = new Thread(new Runnable() {
public void run() {
synchronized (obj) {
try {
System.out.println("进入了wait方法 当前时间是"+ new Date().toLocaleString());
obj.wait();
System.out.println("wait方法结束 当前时间是"+ new Date().toLocaleString());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread.start();

Thread tha = new Thread(new Runnable() {
public void run() {
synchronized (obj) {
obj.notify();
}
}
});
tha.start();
}
}

运行结果:

进入了wait方法 当前时间是2018-7-26 14:32:41
wait方法结束 当前时间是2018-7-26 14:32:41

 

notify()方法
(1)当一个线程处于wait()状态时,也即等待它之前所持有的object's monitor被释放,通过notify()方法可以让该线程重新处于活动状态,从而去抢夺object's monitor,唤醒该线程。
(2)如果多个线程同时处于等待状态,那么调用notify()方法只能随机唤醒一个线程。
(3)在同一时间内,只有一个线程能够获得object's monitor,执行完毕之后,则再将其释放供其它线程抢占。
 
notifyAll()就是用来唤醒正在等待状态中的所有线程
(1)notifyAll()只会唤醒那些等待抢占指定object's monitor的线程,其他线程则不会被唤醒。
(2)notifyAll()只会一个一个的唤醒,而并非统一唤醒。因为在同一时间内,只有一个线程能够持有object's monitor
(3)notifyAll()只是随机的唤醒线程,并非有序唤醒。
那么如何做到有序唤醒是我们接下来要讨论的问题。
posted @ 2018-07-26 11:49  奋斗的渣渣  阅读(327)  评论(0编辑  收藏  举报