【JUC并发】黑马程序员:同步模式之顺序控制 ,wait、await、park三种实现

博客内容展示了使用Java的wait/notify、Lock条件变量以及Park/Unpark三种方式实现多个线程按特定顺序输出字符串'abc'的示例代码。每个线程分别负责输出'a'、'b'和'c',并确保正确顺序。
摘要由CSDN通过智能技术生成

线程 1 输出 a 5 次,线程 2 输出 b 5 次,线程 3 输出 c 5 次。现在要求输出 abcabcabcabcabc 怎么实现

1 wait notify 版

class SynWaitNotify{
    //当前输出信号
    private int signal;
    //输出次数
    private int num;

    public SynWaitNotify(int signal, int num) {
        this.signal = signal;
        this.num = num;
    }
    //输出方法
    public void print(int sign,int next,String message) throws InterruptedException {
        for (int i = 0; i < num; i++) {
            synchronized (this){
                while(signal!=sign){
                    this.wait();
                }
                System.out.print(message);
                signal=next;
                this.notifyAll();
            }
        }
    }
}
@Test
public void demo1(){
        SynWaitNotify synWaitNotify=new SynWaitNotify(1,10);
        new Thread(()->{
            try {
                synWaitNotify.print(1,2,"a");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t1").start();
        new Thread(()->{
            try {
                synWaitNotify.print(2,3,"b");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t2").start();
        new Thread(()->{
            try {
                synWaitNotify.print(3,1,"c");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t3").start();
}

2 Lock 条件变量版

class SynAwaitSignal extends ReentrantLock{
    //输出次数
    private int num;
    public SynAwaitSignal(int num) {
        this.num = num;
    }

    //输出方法
    public void print(Condition sign,Condition next,String message) throws InterruptedException {
        for (int i = 0; i < num; i++) {
            this.lock();
            try {
                sign.await();
                System.out.print(message);
                next.signal();
            }finally {
                this.unlock();
            }
        }
    }
    //唤醒第一个线程
    public void notifyFirst(Condition condition){
        this.lock();
        try {
            condition.signal();
        }finally {
            this.unlock();
        }
    }
}
@Test
public void demo2(){
        SynAwaitSignal synAwaitSignal=new SynAwaitSignal(10);
        Condition condition1=synAwaitSignal.newCondition();
        Condition condition2=synAwaitSignal.newCondition();
        Condition condition3=synAwaitSignal.newCondition();
        new Thread(()->{
            try {
                synAwaitSignal.print(condition1,condition2,"a");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t1").start();
        new Thread(()->{
            try {
                synAwaitSignal.print(condition2,condition3,"b");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t2").start();
        new Thread(()->{
            try {
                synAwaitSignal.print(condition3,condition1,"c");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t3").start();
        synAwaitSignal.notifyFirst(condition1);
}

注意

该实现没有考虑 a,b,c 线程都就绪再开始

2.3 Park Unpark 版

class SynParkUnpark{
    //输出次数
    private int num;
    //下一次唤醒的线程
    private int next;
    //线程集合
    private Thread[] list;
    public SynParkUnpark(int num) {
        this.num = num;
    }

    //将线程加入到线程数组中
    public void setThreads(Thread ...threads){
        list=threads;
    }
    //启动所有线程并唤醒指定线程
    public void startThreads(Thread thread){
        for (Thread th : list) {
            th.start();
        }
        LockSupport.unpark(thread);
    }

    public void print(String a) {
        for (int i = 0; i < num; i++) {
            LockSupport.park();
            System.out.print(a);
            for (int j = 0; j < list.length; j++) {
                if(list[j]==Thread.currentThread()){
                    if(j==list.length-1){
                        next=0;
                    }else{
                        next=j+1;
                    }
                }
            }
            LockSupport.unpark(list[next]);
        }
    }
}
@Test
public void demo3(){
        SynParkUnpark synParkUnpark=new SynParkUnpark(10);
        Thread t1=new Thread(()->{
            synParkUnpark.print("a");
        },"t1");
        Thread t2=new Thread(()->{
            synParkUnpark.print("b");
        },"t2");
        Thread t3=new Thread(()->{
            synParkUnpark.print("c");
        },"t3");
        synParkUnpark.setThreads(t1,t2,t3);
        synParkUnpark.startThreads(t1);
}
2.4 输出
abcabcabcabcabcabcabcabcabcabc
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

愿你满腹经纶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值