一恕刘,sleep和wait方法的區(qū)別
1.從源碼來看
sleep 是Thread類的方法鹃锈,而且時(shí)一個(gè)native修飾的方法,是一個(gè)原生的方法
/**
* Causes the currently executing thread to sleep (temporarily cease
* execution) for the specified number of milliseconds, subject to
* the precision and accuracy of system timers and schedulers. The thread
* does not lose ownership of any monitors.
*
* @param millis
* the length of time to sleep in milliseconds
*
* @throws IllegalArgumentException
* if the value of {@code millis} is negative
*
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* <i>interrupted status</i> of the current thread is
* cleared when this exception is thrown.
*/
public static native void sleep(long millis) throws InterruptedException;
wait方法是Object類的方法
/**
* Causes the current thread to wait until another thread invokes the
* {@link java.lang.Object#notify()} method or the
* {@link java.lang.Object#notifyAll()} method for this object.
* In other words, this method behaves exactly as if it simply
* performs the call {@code wait(0)}.
* <p>
* The current thread must own this object's monitor. The thread
* releases ownership of this monitor and waits until another thread
* notifies threads waiting on this object's monitor to wake up
* either through a call to the {@code notify} method or the
* {@code notifyAll} method. The thread then waits until it can
* re-obtain ownership of the monitor and resumes execution.
* <p>
* As in the one argument version, interrupts and spurious wakeups are
* possible, and this method should always be used in a loop:
* <pre>
* synchronized (obj) {
* while (<condition does not hold>)
* obj.wait();
* ... // Perform action appropriate to condition
* }
* </pre>
* This method should only be called by a thread that is the owner
* of this object's monitor. See the {@code notify} method for a
* description of the ways in which a thread can become the owner of
* a monitor.
*
* @throws IllegalMonitorStateException if the current thread is not
* the owner of the object's monitor.
* @throws InterruptedException if any thread interrupted the
* current thread before or while the current thread
* was waiting for a notification. The <i>interrupted
* status</i> of the current thread is cleared when
* this exception is thrown.
* @see java.lang.Object#notify()
* @see java.lang.Object#notifyAll()
*/
public final void wait() throws InterruptedException {
wait(0);
}
2.調(diào)用方式的不同
- sleep外部可以使。
- wait只能夠在synchronized中使用(從上邊方法的描述中也可以看出他的使用方式,方法的掛起必須要有notify或者notifyAll來通知他去開始競(jìng)爭(zhēng)資源)
3.對(duì)資源的控制不同
sleep的時(shí)候是不會(huì)釋放鎖和cpu的,wait會(huì)釋放資源(cpu,鎖)
這也是下面例子中要著重說的
二媒佣,說明示例
代碼段1:驗(yàn)證wait()方法是會(huì)釋放鎖和cpu資源的
線程A中使用wait去進(jìn)行等待, 在啟動(dòng)完A時(shí),A線程掛起陵刹,等待通知去競(jìng)爭(zhēng)鎖默伍,主線程睡眠20毫秒,啟動(dòng)BBB線程,B線程睡20毫秒,之后通知A線程去競(jìng)爭(zhēng)鎖衰琐。
public static void main(String[] args) {
//創(chuàng)建鎖對(duì)象
final Object lock = new Object();
// 線程AAA
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("thread AAA is waiting to get lock");
synchronized (lock) {
System.out.println("thread AAA get lock ");
try {
System.out.println("thread AAA do wait method");
//Thread.sleep(10);
lock.wait();
System.out.println("thread AAA is done");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
try {
//主線程睡眠10毫秒等待讓兩個(gè)線程啟動(dòng)有個(gè)競(jìng)爭(zhēng)鎖的過程
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 線程BBB
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("thread BBB is waiting to get lock");
synchronized (lock) {
System.out.println("thread BBB get lock ");
try {
Thread.sleep(20);
System.out.println("thread BBB do wait method");
System.out.println("thread BBB is done");
lock.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
執(zhí)行上邊代碼結(jié)果(多次執(zhí)行結(jié)果一致)
thread AAA is waiting to get lock
thread AAA get lock
thread AAA do wait method
thread BBB is waiting to get lock
thread BBB get lock
thread BBB do wait method
thread BBB is done
thread AAA is done
從打印的日志可以看出也糊,AAA 拿到lock鎖之后寨蹋,執(zhí)行wait方法被線程被掛起來了,然后BBB線程啟動(dòng)堵漱,但是BBB獲取到了Lock鎖嚎杨,進(jìn)行了下一步的執(zhí)行,并通知A線程去競(jìng)爭(zhēng)鎖和資源防泵,可以看出,AAA線程在wait方法掛起時(shí)是釋放了鎖和cpu等資源的,否則將會(huì)進(jìn)入無期限的等待當(dāng)中斗搞,不清楚的化可以對(duì)比執(zhí)行第二段代碼,只是將AAA中等待方法替換成了sleep等待方法
代碼的2
此段代碼中讓線程AAA睡眠40毫秒慷妙,讓線程BBB能夠在AAA線程的執(zhí)行過程中啟動(dòng)去競(jìng)爭(zhēng)鎖僻焚。
public static void main(String[] args) {
//創(chuàng)建鎖對(duì)象
final Object lock = new Object();
// 線程AAA
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("thread AAA is waiting to get lock");
synchronized (lock) {
System.out.println("thread AAA get lock ");
try {
System.out.println("thread AAA do wait method");
Thread.sleep(40);
// Thread.sleep(20);
System.out.println("thread AAA is done");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
try {
//主線程睡眠10毫秒等待讓兩個(gè)線程啟動(dòng)有個(gè)競(jìng)爭(zhēng)鎖的過程
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 線程BBB
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("thread BBB is waiting to get lock");
synchronized (lock) {
System.out.println("thread BBB get lock ");
try {
Thread.sleep(20);
System.out.println("thread BBB do wait method");
System.out.println("thread BBB is done");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
多次執(zhí)行結(jié)果如下
thread AAA is waiting to get lock
thread AAA get lock
thread AAA do wait method
thread BBB is waiting to get lock
thread AAA is done
thread BBB get lock
thread BBB do wait method
thread BBB is done
從執(zhí)行結(jié)果可以看到膝擂,BBB的線程雖然是在AAA線程的執(zhí)行過程中啟動(dòng)了虑啤,但是一直沒有獲取到lock鎖,一直在等待架馋,當(dāng)AAA線程執(zhí)行完之后狞山,BBB才獲取到鎖,所以線程使用再使用sleep方法睡眠時(shí)并沒有釋放鎖和cpu資源叉寂。