一 LockSupport的作用
1.1 locksupport作用
locksupport阻塞当前线程和唤醒指定阻塞的线程。
locksupport是一个线程阻塞工具类,所有的方法都是静态的,可以让线程任务阻塞,阻塞之后也有对应的唤醒方法,归根接底,locksupport调用的是unsafe的native代码。
a)当调用park方法时
b)如果有凭证,则会直接消耗掉这个凭证然后退出。
如果无凭证,就必须阻塞等待凭证可用。
当调用unpark时,他会增加一个凭证,但凭证最多有1个,累加无效。
locksupport和每个使用的他的线程都有1个许可关联。当调用unpark获得一个凭证后,再调用park,就可以消费不会阻塞,但是唤醒两次,阻塞两次;而调用两次park;需要两个凭证;unpark调用2次,也只有1个凭证,故剩余一次的park还会阻塞。
1.2 实现等待唤醒的3种方式
1.方式1:使用object的wait()方法让线程等待,使用object中的notify()方法唤醒线程。object的wait和notify 必须使用同一把锁,且wait必须优先notify执行,才ok1
2.方式2:使用juc包中的condition的await()方法让线程等待,使用signal()方法唤醒线程。condition中的await和singal 必须放到锁中,且wait必须优先notify执行,才ok1
3.方式3:使用locksupport类可以阻塞当前线程以及唤醒指定被阻塞的线程。locksupport 先执行unpark后执行park,均可以,但是必须成对出现。
如下图:
1.3 实现方式
1.3.1 LockSupport
locksupport 先执行unpark后执行park,均可以,但是必须成对出现。
package com.ljf.thread.lockSupport;
import java.util.concurrent.locks.LockSupport;
/**
* @ClassName: Huanxing1
* @Description: TODO
* @Author: admin
* @Date: 2024/03/14 23:12:15
* @Version: V1.0
**/
public class Huanxing1 {
public static void main(String[] args) {
// LockSupport lockSupport=
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("t1阻塞");
LockSupport.park();
System.out.println("t1释放阻塞...");
}
});
t1.start();
new Thread(new Runnable() {
@Override
public void run() {
LockSupport.unpark(t1);
System.out.println("唤醒t1");
}
}).start();
}
}
1.3.2 使用Lock
condition中的await和singal 必须放到锁中,且wait必须优先notify执行,才ok1
1.3.3 使用synchronize
object的wait和notify 必须使用同一把锁,且wait必须优先notify执行,才ok1
public class SynDemo {
public static void main(String[] args) {
Object obj=new Object();
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
synchronized (obj){
try {
System.out.println("t1等待");
obj.wait();
System.out.println("t1被释放");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
});
t1.start();
Thread t2=new Thread(new Runnable() {
@Override
public void run() {
synchronized (obj){
try {
Thread.sleep(3000);
System.out.println("t2通知释放t1");
obj.notify();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
});
t2.start();
}
}