package ConcurrentDemo;
//经典并发题:利用三个线程交替输出abcabcabcabc
import org.junit.Test;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
/*
解题技巧:
1.利用等待/通知 wait/notify
2.await/signal
3.park/unpark
*/
public class ABCAlternateDemo {
public static void main(String[] args) {
}
@Test
public void waitAndNotifyTest(){
Message message=new Message(1,4);
new Thread(()-> {
message.print("a",1,2);
},"t1").start();
new Thread(()-> {
message.print("b",2,3);
},"t2").start();
new Thread(()-> {
message.print("c",3,1);
},"t3").start();
}
@Test
public void awaitAndSignalTest() throws InterruptedException {
AwaitSignal aw=new AwaitSignal(4);
Condition con1=aw.newCondition();
Condition con2=aw.newCondition();
Condition con3=aw.newCondition();
new Thread(()-> {
aw.print("a",con1,con2);
},"t1").start();
new Thread(()-> {
aw.print("b",con2,con3);
},"t2").start();
new Thread(()-> {
aw.print("c",con3,con1);
},"t3").start();
TimeUnit.SECONDS.sleep(1);
aw.lock();
try {
con1.signal();//主线程唤醒线程1
}finally {
aw.unlock();
}
}
static Thread t1,t2,t3;
@Test
public void parkAndUparkTest(){
ParkAndUnpark pau=new ParkAndUnpark(4);
t1= new Thread(()-> { pau.print("a",t2);},"t1");
t2= new Thread(()-> {pau.print("b",t3);},"t2");
t3=new Thread(()-> { pau.print("c",t1); },"t3");
t1.start();
t2.start();
t3.start();
LockSupport.unpark(t1);//主线程唤醒线程1
}
}
class Message{
private int flag;
private int loopNumber;
public Message(int flag, int loopNumber) {
this.flag = flag;
this.loopNumber = loopNumber;
}
public void print(String word, int startFlag, int endFlag){
for (int i=0; i<loopNumber ;i++) {
synchronized (this) {
while (flag != startFlag) {
try {
this.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.print(word);
flag = endFlag;
this.notifyAll();
}
}
}
}
class AwaitSignal extends ReentrantLock{
private int loopNumber;
public AwaitSignal(int loopNumber){
this.loopNumber = loopNumber;
}
public void print(String word, Condition waitRoom, Condition signalRoom){
//这种方案不能避免虚假唤醒,只是当前程序只有三个打印线程
for (int i=0; i<loopNumber ;i++) {
lock();
try{
//所有线程一开始就进入对应等待室,等待被唤醒
waitRoom.await();
System.out.print(word);
signalRoom.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
unlock();
}
}
}
}
class ParkAndUnpark{
private int loopNumber;
public ParkAndUnpark(int loopNumber){
this.loopNumber = loopNumber;
}
public void print(String word, Thread thread){
for (int i=0; i<loopNumber ;i++) {
LockSupport.park();
System.out.print(word);
LockSupport.unpark(thread);
}
}
}
【并发编程】多个线程交替输出的经典例题:wait/notify、await/signal 、park/unpark
最新推荐文章于 2022-11-15 22:13:09 发布