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相關的等待池中移走所有線程。