sleep()和wait()方法最大的区别就是:
1.
wait()方法会释放对象的锁,即在线程A wait期间,其他线程可以调用它的synchronized同步方法。
但是线程A sleep的时候,不会释放对象的锁。
其他的区别:
2.
Object类中的方法:wait() / notify() / notifyAll()
Thread类中的方法:sleep() / yield()
3.
wait()方法只能由持有对象锁的线程来调用(即wait()方法必须在同步块内执行),否则会抛出异常java.lang.IllegalMonitorStateException。
而sleep()方法任何线程都可以调用。
一, sleep()方法的使用
public class MyThread1 implements Runnable {
static int a =0;
public static void main(String[] args) {
// TODO Auto-generated method stub
MyThread1 R = new MyThread1();
Thread t1 = new Thread(R,"A");
Thread t2 = new Thread(R,"B");
t1.start();
t2.start();
}
@Override
public synchronized void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++){
a++;
if(a==5){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"--> a = "+a);
// this.notify();
}
}
}
打印出来的log:
A--> a = 1
A--> a = 2
A--> a = 3
A--> a = 4
A--> a = 5
A--> a = 6
A--> a = 7
A--> a = 8
A--> a = 9
A--> a = 10
B--> a = 11
B--> a = 12
B--> a = 13
B--> a = 14
B--> a = 15
B--> a = 16
B--> a = 17
B--> a = 18
B--> a = 19
B--> a = 20
由log可以看出,当a==5时,即使线程A通过sleep(1000)暂停了一秒,但线程B也不会开始执行,还是会等线程A执行完才执行。
二.将sleep()方法换成wait()方法
public class MyThread1 implements Runnable {
static int a =0;
public static void main(String[] args) {
// TODO Auto-generated method stub
MyThread1 R = new MyThread1();
Thread t1 = new Thread(R,"A");
Thread t2 = new Thread(R,"B");
t1.start();
t2.start();
}
@Override
public synchronized void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++){
a++;
if(a==5){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"--> a = "+a);
this.notify();
}
}
}
打印出来的log:
A--> a = 1
A--> a = 2
A--> a = 3
A--> a = 4
B--> a = 6
B--> a = 7
B--> a = 8
B--> a = 9
B--> a = 10
B--> a = 11
B--> a = 12
B--> a = 13
B--> a = 14
B--> a = 15
A--> a = 15
A--> a = 16
A--> a = 17
A--> a = 18
A--> a = 19
A--> a = 20
由log可以看出,当a==5时,线程A wait(),此时线程A释放了对象R的锁,所以线程B可以开始执行,直到线程B执行结束后,线程A才接着上次的进度继续执行。所以有下面的log:
B--> a = 15
A--> a = 15
线程A调用wait()方法后,线程A将进入与对象R相关的等待池中(相当于处于阻塞状态),当线程B调用notify()方法后,将从与对象R相关的等待池中移走任意一个线程(在这里是移走线程A),此时线程A就一直等待(相当于处于就绪状态),直到获取对象R的锁(在这里是线程B执行完后,线程A获取对象R的锁),获取对象锁后,线程A从上一次中断的地方继续执行。
如果对象R相关的等待池中没有线程,那么notify()将不起作用。
notifyAll()的作用是移走与对象R相关的等待池中移走所有线程。