多線程 -- sleep()方法和wait()方法區別

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


發佈了56 篇原創文章 · 獲贊 17 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章