在java.util.concurrent.locks包下
使用java在线API:
https://www.matools.com/api/java8
LockSupport是线程的wait/notify的改良加强版
LOckSupport的park和unpark的作用分别是阻塞线程与解除阻塞线程的事
三种线程的等待/唤醒方法
1.Object对象的wait方法使线程等待,notify方法唤醒线程
注意:不在同一个代码块等待和唤醒功能是不能被用的,会报异常
注意:要等待在前,唤醒在后。如果唤醒在前。等待在后,则线程将会一直等待。
实例1
package com.example.demo.LockTest;
/**
* 编写wait-notify
* 注意:wait-notify要在同一个代码块里面
* 注意:要wait在前,notify在后
* @author Ric
*/
public class WaitNotifyTest {
static Object object = new Object();
public static void main(String[] args) {
new Thread(()->{
synchronized (object){
System.out.println(Thread.currentThread().getName()+"进入");
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"被唤醒");
}
},"线程1").start();
new Thread(()->{
synchronized (object){
object.notifyAll();
System.out.println(Thread.currentThread().getName()+"通知唤醒所有线程");
}
},"线程2").start();
}
}
结果:
线程1进入
线程2通知唤醒所有线程
线程1被唤醒
2.JUC的Condition里面的await是线程等待,signal唤醒线程
实例2
package com.example.demo.LockTest;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* Condition的 Await 与 Signal
* 注意: lock与 unlock是成对出现
* await与signal必须在锁(Lock与unlock)里面
* await必须在signal前面,不然线程会一直等待
* @author Ric
*/
public class AwaitSignalTest {
static ReentrantLock reentrantLock = new ReentrantLock();
static Condition condition = reentrantLock.newCondition();
public static void main(String[] args) {
new Thread(()->{
//显示锁需要在加锁后面紧跟 try-catch-finally 进行解锁
reentrantLock.lock();
try {
System.out.println(Thread.currentThread().getName()+"进入ReentrantLock加锁代码块");
condition.await();
System.out.println(Thread.currentThread().getName()+"已被唤醒");
}catch (Exception e){
e.printStackTrace();
}finally {
reentrantLock.unlock();
}
},"线程1").start();
new Thread(()->{
//显示锁需要在加锁后面紧跟 try-catch-finally 进行解锁
reentrantLock.lock();
try {
condition.signalAll();
System.out.println(Thread.currentThread().getName()+"进行线程唤醒");
}catch (Exception e){
e.printStackTrace();
}finally {
reentrantLock.unlock();
}
},"线程2").start();
}
}
展示结果
线程1进入ReentrantLock加锁代码块
线程2进行线程唤醒
线程1已被唤醒
3.LockSupport的park阻塞线程,unpark解除阻塞线程。
lockSupport的park与unpark相当于设置信号量(许可证),许可证不能累加,初始值为0,unpark一次加1,但是不能大于1,park一次减1.但是不能小于0。所以许可证的值只能为0和1.
实例1:
package com.example.demo.LockTest;
import java.util.concurrent.locks.LockSupport;
/**
* 测试LockSupport的park与unpark
* 注意:LockSupport的构造方法是私有的 直接通过LockSupport这个类来访问
* LockSupport直接通过类进行方法访问
* park()默认许可证为 0 unpark()使许可证为 1 许可证只能为 0 和 1
* 许可证为 1 表示能唤醒一次该目标线程
*
* park() 与 unpark() 没有先后顺序之分
*/
public class LockSupportTest {
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "进入");
//阻塞 许可证默认为 0
LockSupport.park();
System.out.println(Thread.currentThread().getName() + "已被唤醒");
}, "线程1");
thread1.start();
new Thread(()->{
//许可证为1 就算多次park()许可证还是为1
//传入要被唤醒的线程,让该线程的许可证为 1,可以被唤醒
LockSupport.unpark(thread1);
System.out.println(Thread.currentThread().getName()+"唤醒"+thread1.getName());
},"线程2").start();
}
}
示例结果:
线程1进入
线程2唤醒线程1
线程1已被唤醒