🌕 🌗 1114. 按序打印

吞佛童子2022年6月20日
  • algorithm
  • 多线程
大约 2 分钟

🌕 🌗 1114. 按序打印

难度: 🌕 🌗

问题描述

img_1.png


解法 1 - ReentrantLock + Condition

class Foo {
    private int flag; // 设置标志值,只有 == 对应标志值时,才能运行该线程
    ReentrantLock lock;
    Condition condition1;
    Condition condition2;
    Condition condition3;

    public Foo() {
        this.flag = 1;
        this.lock = new ReentrantLock();
        this.condition1 = lock.newCondition();
        this.condition2 = lock.newCondition();
        this.condition3 = lock.newCondition();
    }

    public void first(Runnable printFirst) throws InterruptedException {
        
        // printFirst.run() outputs "first". Do not change or remove this line.
        lock.lock();
        try {
            while(flag != 1) { // while 防虚假唤醒
                condition1.await(); // 等待 & 释放锁
            }
            printFirst.run();
            flag = 2;
            // 如果 condition2 有节点,说明之前有线程先执行了 second 方法,并被送入了等待队列,需要唤醒
            condition2.signal(); 
        } finally {
            lock.unlock(); // 释放锁
        }
    }

    public void second(Runnable printSecond) throws InterruptedException {
        
        // printSecond.run() outputs "second". Do not change or remove this line.
        lock.lock();
        try {
            while(flag != 2) {
                condition2.await();
            }
            printSecond.run();
            flag = 3;
            condition3.signal();
        } finally {
            lock.unlock();
        }  
    }

    public void third(Runnable printThird) throws InterruptedException {
        
        // printThird.run() outputs "third". Do not change or remove this line.
        lock.lock();
        try {
            while(flag != 3) {
                condition3.await();
            }
            printThird.run();
            flag = 0;
        } finally {
            lock.unlock();
        }
        
    }
}

输出 1

img.png


解法 2 - CountDownLatch

class Foo {
    // method 2 - CountDownLatch
    CountDownLatch c12; // 计数器,设置初始容量,当减到 0 时可以启动
    CountDownLatch c23;

    public Foo() {
        c12 = new CountDownLatch(1);
        c23 = new CountDownLatch(1);
    }

    public void first(Runnable printFirst) throws InterruptedException {

        printFirst.run();
        c12.countDown();
    }

    public void second(Runnable printSecond) throws InterruptedException {
        
        c12.await(); // 阻塞直到 c12 == 0
        printSecond.run();
        c23.countDown();
    }

    public void third(Runnable printThird) throws InterruptedException {
        
        c23.await();
        printThird.run();
    }
}

输出 2

img_2.png


解法 3 - Semaphore

class Foo {
    // method 3 - Semaphore - 获取值,获取成功则执行
    Semaphore s12;
    Semaphore s23;

    public Foo() {
        s12 = new Semaphore(0);
        s23 = new Semaphore(0);
    }

    public void first(Runnable printFirst) throws InterruptedException {
        
        printFirst.run();
        s12.release(); // 发放一个许可
    }

    public void second(Runnable printSecond) throws InterruptedException {
        
        s12.acquire(); // 尝试获取一个许可,获取不到则阻塞等待
        printSecond.run();
        s23.release();
    }

    public void third(Runnable printThird) throws InterruptedException {
        
        s23.acquire();
        printThird.run();
    }
}

输出 3

img_3.png


解法 4 - SynchronousQueue

class Foo {
    // method 4 - SynchronousQueue 当里面有元素时,阻塞放入,只有里面的元素被 take() 时才能继续放入
    BlockingQueue<Integer> queue12;
    BlockingQueue<Integer> queue23;

    public Foo() {
        queue12 = new SynchronousQueue<>();
        queue23 = new SynchronousQueue<>();
    }

    public void first(Runnable printFirst) throws InterruptedException {
        
        printFirst.run();
        queue12.put(1); // 随便放入一个元素
    }

    public void second(Runnable printSecond) throws InterruptedException {
        
        queue12.take(); // 获取不到,则阻塞
        printSecond.run();
        queue23.put(1);
    }

    public void third(Runnable printThird) throws InterruptedException {
        
        queue23.take();
        printThird.run();
    }
}

输出 4

img_4.png

上次编辑于: 2022/6/20 下午8:24:47
贡献者: liuxianzhishou