/*
需求是:有两个线程,一个线程打印1,一个线程打印2,先打印2再打印1
*/
(1)使用wait/notify
@Slf4j(topic = "c.PrintTest")
public class PrintTest {
static final Object lock=new Object();
static boolean t2runed=false;//表示t2是否运行过
public static void main(String[] args) {
//线程1继续执行的条件是看看t2是否已经打印,若条件不满足(t2没有打印)则进入等待,若它t2已经打印,则可以打印1
Thread t1=new Thread(()->{
synchronized (lock){
while(!t2runed){
try{
lock.wait();
}catch (Exception e){
e.printStackTrace();
}
}
}
log.debug("1");
},"t1");
Thread t2=new Thread(()->{
synchronized (lock){
log.debug("2");
t2runed=true;
lock.notify();
}
},"t2");
t1.start();
t2.start();
}
}
//分析:如果t1先执行,那t1先获得锁,然后它去判断t2是否打印了2,发现还没有打印,
//则进入等待队列中进行等待,此时它会释放锁,t2启动后想去执行会由于锁而被阻塞,当t1释放锁时
//它获得到锁后,它先打印2,然后将打印标记置为真,再去唤醒t1,让他打印1,释放锁,结束。
//
//如果t2先执行,它获得到锁,打印2,将打印标记置为true,notify,释放锁,t1再获取锁,判断打印标记,发现为真,
//直接打印1,释放锁,结束。
(2)使用park()和unpack()
@Slf4j(topic = "c.PrintTest2")
public class PrintTest2 {
public static void main(String[] args) {
Thread t1=new Thread(()->{
LockSupport.park();
log.debug("1");
},"t1");
t1.start();
new Thread(()->{
log.debug("2");
LockSupport.unpark(t1);
},"t2").start();
}
}
//分析,如果是t1先运行,它会先暂停,接着t2运行,打印2之后将t1唤醒,打印1
//如果是t2先运行,它先打印2,然后unpark(t1),相当于提前给t1补充好了干粮,当t1运行时,不会再暂停(相当于干粮充足)直接打印1