@Slf4j(topic = "c.Test25")
public class Test25 {
static final Object lock = new Object();
// 表示 t2 是否运行过
static boolean t2runned = false;
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
synchronized (lock) {
while (!t2runned) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.debug("1");
}
}, "t1");
Thread t2 = new Thread(() -> {
synchronized (lock) {
log.debug("2");
t2runned = true;
lock.notify();
}
}, "t2");
t1.start();
t2.start();
}
}
public class ABThread {
static final Lock lock = new ReentrantLock();
static final Condition condition = lock.newCondition();
// 表示 t2 是否运行过
static boolean t2runned = false;
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
lock.lock();
try {
while (!t2runned) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(("1"));
} finally {
lock.unlock();
}
}, "t1");
Thread t2 = new Thread(() -> {
lock.lock();
try {
System.out.println(("2"));
t2runned = true;
condition.signal();
} finally {
lock.unlock();
}
}, "t2");
t1.start();
Thread.sleep(500);
t2.start();
}
}
@Slf4j(topic = "c.Test26")
public class Test26 {
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();
}
}
<aside> 💡 注意 park 和 unpark 的特性,如果先 unpark,则 park 不会生效
</aside>
<aside> 💡 重点,面试常考
</aside>
public class Test27 {
public static void main(String[] args) {
WaitNotify wn = new WaitNotify(1, 5);
new Thread(() -> {
wn.print("a", 1, 2);
}).start();
new Thread(() -> {
wn.print("b", 2, 3);
}).start();
new Thread(() -> {
wn.print("c", 3, 1);
}).start();
}
}
/*
输出内容 等待标记 下一个标记
a 1 2
b 2 3
c 3 1
*/
class WaitNotify {
// 打印 a 1 2
public void print(String str, int waitFlag, int nextFlag) {
for (int i = 0; i < loopNumber; i++) {
synchronized (this) {
while(flag != waitFlag) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(str);
flag = nextFlag;
this.notifyAll();
}
}
}
// 等待标记
private int flag; // 2
// 循环次数
private int loopNumber;
public WaitNotify(int flag, int loopNumber) {
this.flag = flag;
this.loopNumber = loopNumber;
}
}
原理:Monitor 监视器,synchronized 锁原理
public class Test30 {
public static void main(String[] args) throws InterruptedException {
AwaitSignal awaitSignal = new AwaitSignal(5);
Condition a = awaitSignal.newCondition();
Condition b = awaitSignal.newCondition();
Condition c = awaitSignal.newCondition();
new Thread(() -> {
awaitSignal.print("a", a, b);
}).start();
new Thread(() -> {
awaitSignal.print("b", b, c);
}).start();
new Thread(() -> {
awaitSignal.print("c", c, a);
}).start();
Thread.sleep(1000);
awaitSignal.lock();
try {
System.out.println("开始...");
a.signal();
} finally {
awaitSignal.unlock();
}
}
}
class AwaitSignal extends ReentrantLock{
private int loopNumber;
public AwaitSignal(int loopNumber) {
this.loopNumber = loopNumber;
}
// 参数1 打印内容, 参数2 进入哪一间休息室, 参数3 下一间休息室
public void print(String str, Condition current, Condition next) {
for (int i = 0; i < loopNumber; i++) {
lock();
try {
current.await();
System.out.print(str);
next.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
unlock();
}
}
}
}
public class Test31 {
static Thread t1;
static Thread t2;
static Thread t3;
public static void main(String[] args) {
ParkUnpark pu = new ParkUnpark(5);
t1 = new Thread(() -> {
pu.print("a", t2);
});
t2 = new Thread(() -> {
pu.print("b", t3);
});
t3 = new Thread(() -> {
pu.print("c", t1);
});
t1.start();
t2.start();
t3.start();
LockSupport.unpark(t1);
}
}
class ParkUnpark {
public void print(String str, Thread next) {
for (int i = 0; i < loopNumber; i++) {
LockSupport.park();
System.out.print(str);
LockSupport.unpark(next);
}
}
private int loopNumber;
public ParkUnpark(int loopNumber) {
this.loopNumber = loopNumber;
}
}
我们先定义一个类 ABCPrinter
用于实现三个线程交替打印 ABC。
public class ABCPrinter {
private final int max;
// 从线程 A 开始执行
private final Semaphore semaphoreA = new Semaphore(1);
private final Semaphore semaphoreB = new Semaphore(0);
private final Semaphore semaphoreC = new Semaphore(0);
public ABCPrinter(int max) {
this.max = max;
}
public void printA() {
print("A", semaphoreA, semaphoreB);
}
public void printB() {
print("B", semaphoreB, semaphoreC);
}
public void printC() {
print("C", semaphoreC, semaphoreA);
}
private void print(String alphabet, Semaphore currentSemaphore, Semaphore nextSemaphore) {
for (int i = 1; i <= max; i++) {
try {
currentSemaphore.acquire();
System.out.println(Thread.currentThread().getName() + " : " + alphabet);
// 传递信号给下一个线程
nextSemaphore.release();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
}
}
可以看到,我们这里用到了三个信号量,分别用于控制这三个线程的交替执行。semaphoreA
信号量先获取,也就是先输出“A”。一个线程执行完之后,就释放下一个信号量。也就是,A 线程执行完之后释放semaphoreB
信号量,B 线程执行完之后释放semaphoreC
信号量,以此类推。
接着,我们创建三个线程,分别用于打印 ABC。
ABCPrinter printer = new ABCPrinter(10);
Thread t1 = new Thread(printer::printA, "Thread A");
Thread t2 = new Thread(printer::printB, "Thread B");
Thread t3 = new Thread(printer::printC, "Thread C");
t1.start();
t2.start();
t3.start();
输出如下:
Thread A : A
Thread B : B
Thread C : C
......
Thread A : A
Thread B : B
Thread C : C