使用 Thread.sleep() 方法,会阻塞当前线程,但是在阻塞用户设置的时间后自动进入就绪态,在此期间并不会释放已经获得的同步锁
一. Object 类 提供的方法 wait & notify
1. 使用方式
public class WaitAndNotify {
public static void main(String[] args) {
// 设置对象锁
Object o =new Object();
new Thread(()->{
synchronized (o){
try {
System.out.println(Thread.currentThread().getName() + "\t-----阻塞当前线程");
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "\t-----被唤醒");
}
},"t1").start();
new Thread(()->{
synchronized (o){
o.notify();
System.out.println(Thread.currentThread().getName() + "\t-----发出唤醒通知");
}
},"t2").start();
}
}
2. 执行结果:
3. 注意:
wait 方法将当前持有该锁的线程阻塞直至被 notify 唤醒, wait 和 notify 方法只能写在同步代码块里面
二. Lock + Condition 配合:await & signal
1. 使用方式
public class LockAndCondition {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
new Thread(()->{
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "\t-----come in");
condition.await();
System.out.println(Thread.currentThread().getName() + "\t-----被唤醒");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
},"t1").start();
try {TimeUnit.MILLISECONDS.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}
new Thread(()->{
lock.lock();
try{
System.out.println(Thread.currentThread().getName() + "\t-----come in");
condition.signal();
System.out.println(Thread.currentThread().getName() + "\t-----发出唤醒通知");
}finally {
lock.unlock();
}
},"t2").start();
}
}
2. 运行结果:
3. 注意:
await 和 signal 方法也必须写在 lock 和 unlock 同步方法块中
三. LockSupport 中的 park 和 unpark 方法
1. 使用方式
public class ParkAndUnpark {
public static void main(String[] args) {
Thread t1 = new Thread(()->{
System.out.println(Thread.currentThread().getName() + "\t-----come in");
LockSupport.park();
System.out.println(Thread.currentThread().getName() + "\t-----被唤醒");
},"t1");
t1.start();
try { TimeUnit.MILLISECONDS.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}
new Thread(()->{
System.out.println(Thread.currentThread().getName() + "\t-----come in");
LockSupport.unpark(t1);
System.out.println(Thread.currentThread().getName() + "\t-----发出唤醒通知");
},"t2").start();
}
}
2. 执行结果
3. 注意
1)不需要写在同步代码块中,成对出现
2)支持先 unpark 获得通行证,park 并不会进行阻塞
3)通过unpark提前获得的通行证,最多只有一个,重复多个只有一个生效