Sleep vs Wait
java虚拟机支持多线程开发。在多线程开发中我们可以用线程来启动、执行、结束某些程序控制。在多线程同步开发中我们会接触到两个不同的方法——wait 和 sleep
wait和sleep都是用来控制线程的执行与等待方法。sleep方法是让当前线程延迟一段时间再执行下一句程序指令,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属于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通过两个线程,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块才能往下继续执行。
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锁的代码。