【多线程学习十】同步模式之顺序控制

同步模式之顺序控制

必须先 2 后 1 打印

使用wait notify

@Slf4j
public class SequenceWait {
    static Object obj = new Object();
//    判断t2是否已经运行
    static boolean ist2runned = false;
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            synchronized (obj){
//                当t2正在运行时,t1进入等待
                while (!ist2runned){
                    try{
                        obj.wait();
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                }
                log.info("t1 start....");
            }
        });

        Thread t2 = new Thread(() -> {
            log.info("t2 start....");
            synchronized (obj){
                ist2runned = true;
//                通知等待的线程
                obj.notifyAll();
            }
        });

        t1.start();
        t2.start();

    }
}

执行结果
在这里插入图片描述

使用park unpark

  • 使用wait和notify的方式需要保证先wait后notify,否则wait永远得不到唤醒,需要【运行标记】去判断需不需要wait
  • 使用while防止虚假唤醒
  • 唤醒对象上的wait需要使用notifyAll,防止等待线程不止一个
  public static void main(String[] args) {
        Thread t1 = new Thread(()->{
            LockSupport.park();
            log.info("t1 start ....");
        },"t1");

        Thread t2 = new Thread(()->{
            log.info("t2 start ....");
            LockSupport.unpark(t1);
        },"t2");

        t1.start();
        t2.start();
    }

在这里插入图片描述

使用了park和unpark,利用了以线程为单位的特点,不需要【同步对象】和【运行标记】

交替输出

使用wait和notifyAll

@Slf4j
public class SyncWaitNotify {
    private int flag;
//    循环次数
    private int loopNumber;

    public SyncWaitNotify(int flag, int loopNumber) {
        this.flag = flag;
        this.loopNumber = loopNumber;
    }

    public void print(int waitFlag, int nextFlag, String str){
        for(int i=0;i<loopNumber;i++){
            synchronized (this){
                while(this.flag != waitFlag){
                    try {
                        this.wait();
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                }
                log.info(str);
                flag = nextFlag;
                this.notifyAll();
            }
        }
    }
}

 public static void main(String[] args) {
        SyncWaitNotify sn = new SyncWaitNotify(1,5);

        new  Thread(()->{
            sn.print(1,2,"a");
        }).start();

        new  Thread(()-> {
            sn.print(2, 3, "b");
        }).start();

        new  Thread(()->{
            sn.print(3,1,"c");
        }).start();
    }

条件变量

@Slf4j
public class AwaitSync extends ReentrantLock {
//    循环次数
    private int loopNumber;

    public AwaitSync(int loopNumber){
        this.loopNumber = loopNumber;
    }

    public void print(String str, Condition current, Condition next){
        for(int i=0; i<loopNumber; i++){
            this.lock();
            try {
                current.await();
                log.info(str);
                next.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                this.unlock();
            }
        }
    }

    public void start(Condition first){
        this.lock();
        try {
            log.info("start....");
            first.signal();
        }finally {
            this.unlock();
        }
    }
}
public static void main(String[] args) {
        AwaitSync as = new AwaitSync(5);
        Condition aAwait = as.newCondition();
        Condition bAwait = as.newCondition();
        Condition cAwait = as.newCondition();


        new Thread(()->{
            as.print("a",aAwait,bAwait);
        }).start();

        new Thread(()->{
            as.print("b",bAwait,cAwait);
        }).start();

        new Thread(()->{
            as.print("c",cAwait,aAwait);
        }).start();

        as.start(aAwait);
    }

在这里插入图片描述

使用park unpark

static Thread t1;
    static Thread t2;
    static Thread t3;
    public static void main(String[] args) {
        SyncPark syncPark = new SyncPark(5);
        t1 = new Thread(()->{
            syncPark.print("a",t2);
        });
        t2 = new Thread(()->{
            syncPark.print("b",t3);
        });
        t3 = new Thread(()->{
            syncPark.print("c",t1);
        });
        t1.start();
        t2.start();
        t3.start();

        LockSupport.unpark(t1);
    }
@Slf4j
public class SyncPark {
    private int loopNumber;

    public SyncPark(int loopNumber) {
        this.loopNumber = loopNumber;
    }


    public void print(String str,Thread next){
        for(int i=0; i<loopNumber; i++){
            LockSupport.park();
            log.info(str);
            LockSupport.unpark(next);
        }
    }

}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值