【并发编程】多个线程交替输出的经典例题:wait/notify、await/signal 、park/unpark

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);
        }
    }
}

你可能感兴趣的:(Java)