java多線程知識點之wait和sleep的區別

java多線程知識點之wait和sleep的區別

Sleep vs Wait

java虛擬機支持多線程開發。在多線程開發中我們可以用線程來啓動、執行、結束某些程序控制。在多線程同步開發中我們會接觸到兩個不同的方法——wait 和 sleep

wait和sleep都是用來控制線程的執行與等待方法。sleep方法是讓當前線程延遲一段時間再執行下一句程序指令,wait不會直接讓當前線程延遲控制指令執行,而是讓線程暫時掛起狀態。

一、wait方法:

wait是屬於object類的方法,在java中所有類都是繼承於object類,當調用wait方法時會將調用方法所處的線程切換到掛起不執行狀態。與wait相對應的有notify和notifyAll方法可以讓處於wait的object的線程恢復到運行狀態。

wait方法必須在synchronized同步所內部調用。當object被調用的時候,java虛擬機(後續稱爲系統)釋放object所對應的synchronized的lock鎖,然後再把調用wait的當前線程掛起並添加到wait列表,系統在wait的時候釋放lock鎖是爲了讓其他線程能能夠synchronized加鎖以便於用notify或者notifyAll喚醒wait列表中相應object的線程。

 

二、sleep方法:

sleep屬於Thread線程類的一個靜態方法。調用該方法會是當前線程延遲一段時間後執行下一句控制指令,在延遲這段時間內當前線程並沒有任何object對象被標記掛起或者其他操作。對於synchronized內的sleep方法,在sleep期間其他線程不能夠進入相同synchronized對象內部。

 

三、小節

1. sleep是線程thread類的靜態方法,wait是一個實例化對象的線程控制方法;

2. sleep是thread線程類操作內的方法,wait是任意對象內的方法,範圍不同;

3. sleep方法會保留synchronized內的lock鎖,wait不會保存synchronized內的鎖;

4. 對於synchonized內部執行wait在不執行線程期間不會影響其他線程進入相同的synchronized同步塊,而sleep則不允許在sleep期間其他線程進入synchronized內。

 

=============================================================

# 以上內容來自文章:

http://www.differencebetween.net/technology/software-technology/difference-between-sleep-and-wait/

 

的部分翻譯

=============================================================

在多線程同於應用上的最大區別就是wait可以釋放synchronized中的鎖,而sleep不會釋放。

接下來我們用demo來演示一下這個特性

一、SleepDemo

SleepDemo通過兩個線程,SleepThread線程會在synchronized執行中sleep 3秒鐘,ReadThread線程直接運行,但是會在運行中經過synchronized代碼塊。由於Thread.sleep在延遲執行時不會釋放synchronized持有的鎖,所以ReadThread必須等待SleepThread退出鎖後繼續運行,具體代碼如下

import java.lang.Thread;

public class SleepDemo {
	public static void main(String args[]) {
        Object lock = new Object();
		SleepThread t1 = new SleepThread(lock);
		t1.start();

		// sleep to ensure thread of t1 start before t2
		try {
			Thread.sleep(300);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		ReadThread t2 = new ReadThread(lock);
		t2.start();

		try {
		    t1.join();
		    t2.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

class SleepThread extends Thread {
	Object lock = new Object();

	public SleepThread(Object lock) {
		this.lock = lock;
	}

	@Override
    public void run() {
		System.out.println("SleepThread before synchronized");
		synchronized (lock) {
		    System.out.println("SleepThread enter synchronized");
		    System.out.println("SleepThread before sleep");
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		    System.out.println("SleepThread after sleep");
		    System.out.println("SleepThread exit synchronized");
		}
		System.out.println("SleepThread after synchronized");
	}
}

class ReadThread extends Thread {
	Object lock = new Object();

	public ReadThread(Object lock) {
		this.lock = lock;
	}

	@Override
    public void run() {
		System.out.println("ReadThread before synchronized");
		synchronized (lock) {
		    System.out.println("ReadThread enter synchronized");
		    System.out.println("ReadThread exit synchronized");
		}
		System.out.println("ReadThread after synchronized");
	}
}

編譯:

$ javac SleepDemo.java

$ java SleepDemo

SleepThread before synchronized

SleepThread enter synchronized

SleepThread before sleep

ReadThread before synchronized

SleepThread after sleep

SleepThread exit synchronized

SleepThread after synchronized

ReadThread enter synchronized

ReadThread exit synchronized

ReadThread after synchronized

 

ReadThread準備進入synchronized塊時由於鎖被SleepThread的synchronized持有,必須等待sleep結束後退出synchronized塊才能往下繼續執行。

 

二、WaitDemo

   SleepDemo通過兩個線程,WaitThread線程會在synchronized執行中sleep 3秒鐘,ReadThread線程直接運行,但是會在運行中經過synchronized代碼塊。由於Object.wait在被掛起時釋放synchronized持有的鎖,ReadThread執行synchronized代碼時如果WaitThead已經處於wait狀態時能夠繼續進入synchronized代碼,不需要等待,具體代碼如下

import java.lang.Thread;

public class WaitDemo {
	public static void main(String args[]) {
		Object lock = new Object();
		WaitThread t1 = new WaitThread(lock);
		t1.start();

		// sleep to ensure thread of t1 start before t2
		try {
			Thread.sleep(300);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		ReadThread t2 = new ReadThread(lock);
		t2.start();

		try {
		    t1.join();
		    t2.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

class WaitThread extends Thread {
	Object lock = new Object();

	public WaitThread(Object lock) {
		this.lock = lock;
	}

	@Override
    public void run() {
		System.out.println("WaitThread before synchronized");
		synchronized (lock) {
		    System.out.println("WaitThread enter synchronized");
		    System.out.println("WaitThread before wait");
			try {
				lock.wait(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		    System.out.println("WaitThread after wait");
		    System.out.println("WaitThread exit synchronized");
		}
		System.out.println("WaitThread after synchronized");
	}
}

class ReadThread extends Thread {
	Object lock = new Object();

	public ReadThread(Object lock) {
		this.lock = lock;
	}

	@Override
    public void run() {
		System.out.println("ReadThread before synchronized");
		synchronized (lock) {
		    System.out.println("ReadThread enter synchronized");
		    System.out.println("ReadThread exit synchronized");
		}
		System.out.println("ReadThread after synchronized");
	}
}

編譯運行

$ javac WaitDemo.java

$ java WaitDemo

WaitThread before synchronized

WaitThread enter synchronized

WaitThread before wait

ReadThread before synchronized

ReadThread enter synchronized

ReadThread exit synchronized

ReadThread after synchronized

WaitThread after wait

WaitThread exit synchronized

WaitThread after synchronized

 

可以看看到synchronized調用wait後不會影響其他synchronized鎖的代碼。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章