三种方式总结:
一、synchronized: wait、notify、notifyAll
1、需要结合synchronized使用,否作会出现异常
2、必须先执行wait, 后执行notify或者notifyAll,否作会一直处于阻塞状态
二、Lock.condition: await、signal、signalAll
1、需要结合lock使用,否作会出现异常
2、必须先执行await, 后执行signal或者signalAll, 否作会一直处于阻塞状态
三、LockSupport: park、unpark
1、不依赖其它外部代码
2、park、unpark执行没有先后顺序
3、unpark方法同一时间最多只能获取一个许可证,只能通知一个park方法
package com.scwyfy.knowledge.juc;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
/**
* LockSupport:park()与unpark() 用来阻塞和唤醒线程,不需要手动加锁即可实现,且对阻塞、唤醒顺序无要求
* 注意: 执行多次unpark(),最多也只能获取一个许可证(不会进行累加操作),只能唤醒一个park()
* 例如:先执行两次unpark(),再执行两次park(), 第二个park()将会处于阻塞状态
* Synchronized: wait()与notify()或者notifyAll 用于阻塞和唤醒线程,需要结合Synchronized一起使用,否则将会产生异常 IllegalMonitorStateException
* 且必须先wait(),再notify()。不然将会一直处于阻塞状态
* Lock
* Condition: await()与signal()或者signalAll 用于阻塞和唤醒线程,需要结合Lock一起使用,否则将会产生异常 IllegalMonitorStateException
* 且必须先await(),再signal()。不然将会一直处于阻塞状态
*/
public class LockSupportDemo {
public static void main(String[] args) {
// synchronizedSolution();
// lockSolution();
// lockSupportSolution();
parkAndUnparkDemo();
}
/**
* unpark方法:许可证最多只能有一个
*/
private static void parkAndUnparkDemo() {
Thread thread = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(3L);// 目的先让执行unpark方法
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("准备执行两次park方法");
LockSupport.park();
System.out.println("已执行一次park方法");
LockSupport.park();
System.out.println("park方法执行完成");
});
thread.start();
new Thread(() -> {
System.out.println("准备执行两次unpark方法");
LockSupport.unpark(thread);
LockSupport.unpark(thread);
System.out.println("unpark方法执行完成");
}).start();
}
/**
* LockSupport方式实现 阻塞、唤醒
*/
private static void lockSupportSolution() {
Thread a = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(3L);
System.out.println(Thread.currentThread().getName() + " --- 进入");
} catch (InterruptedException e) {
e.printStackTrace();
}
LockSupport.park(); // 不需要依赖外部代码,park与unpark方法不用区分先后执行顺序
System.out.println(Thread.currentThread().getName() + " --- 出来");
}, "a");
a.start();
Thread b = new Thread(() -> {
LockSupport.unpark(a); // 不需要依赖外部代码,park与unpark方法不用区分先后执行顺序
System.out.println(Thread.currentThread().getName() + " --- 通知");
}, "b");
b.start();
}
/**
* Lock.Condition方式实现阻塞、唤醒
*/
private static void lockSolution() {
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
new Thread(() -> {
try {
// TimeUnit.SECONDS.sleep(3L);// 先signal,再await,会一直处于阻塞状态
lock.lock();
System.out.println(Thread.currentThread().getName() + " --- 进入");
condition.await(); // 不结合lock,await、signal方法会有异常IllegalMonitorStateException
System.out.println(Thread.currentThread().getName() + " --- 出来");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}, "A").start();
new Thread(() -> {
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + " --- 通知");
condition.signal();
} finally {
lock.unlock();
}
}, "B").start();
}
/**
* synchronized方式实现阻塞、唤醒
*/
private static void synchronizedSolution() {
Object synchronizedLock = new Object();
new Thread(() -> {
try {
// TimeUnit.SECONDS.sleep(3L); // 先notify,再wait。会一直阻塞状态
synchronized (synchronizedLock) {// 不结合synchronized, wait、notify方法会有异常IllegalMonitorStateException
System.out.println(Thread.currentThread().getName() + " --- 进入");
synchronizedLock.wait();
System.out.println(Thread.currentThread().getName() + " --- 出来");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "A").start();
new Thread(() -> {
synchronized(synchronizedLock) {
synchronizedLock.notify();
System.out.println(Thread.currentThread().getName() + " --- 通知");
}
}, "B").start();
}
}