🌕 🌗 1115. 交替打印 FooBar

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

🌕 🌗 1115. 交替打印 FooBar

难度: 🌕 🌗

问题描述

img_6.png


解法 1 - CyclicBarrier + flag

class FooBar {
    // 思路: CyclicBarrier 循环栅栏
    private int n;
    CyclicBarrier c;
    private int flag; // 标志位

    public FooBar(int n) {
        this.n = n;
        this.c = new CyclicBarrier(2);
        this.flag = 1;
    }

    public void foo(Runnable printFoo) throws InterruptedException {
        
        for (int i = 0; i < n; i++) {
            while(flag != 1) {
            }
        	printFoo.run();
            flag = 2;
            try {
                c.await(); // 执行 await() 会使容量 --
            } catch (BrokenBarrierException e) {}
        }
    }

    public void bar(Runnable printBar) throws InterruptedException {
        
        for (int i = 0; i < n; i++) {
            while(flag != 2) {
            }
            flag = 1;
        	printBar.run();
            try {
                c.await();
            } catch (BrokenBarrierException e) {}
        }
    }
}

输出 1

img_5.png


解法 2 - ReentrantLock + Condition + flag

class FooBar {
    // 思路:
    // ReentrantLock + Condition
    private int n;
    ReentrantLock lock;
    Condition c;
    private int flag;

    public FooBar(int n) {
        this.n = n;
        this.lock = new ReentrantLock();
        this.c = lock.newCondition();
        this.flag = 1;
    }

    public void foo(Runnable printFoo) throws InterruptedException {
        
        for (int i = 0; i < n; i++) {
            lock.lock();
            try {
                while(flag != 1) {
                c.await(); // 进入 c 等待队列
                }
                printFoo.run();
                flag = 2;
                c.signal(); // 唤醒 c 等待队列
            } finally {
                lock.unlock();
            }
        }
    }

    public void bar(Runnable printBar) throws InterruptedException {
        
        for (int i = 0; i < n; i++) {
            lock.lock();
        	
            try {
                while(flag != 2) {
                    c.await();
                }
                printBar.run();
                flag = 1;
                c.signal();
            } finally {
                lock.unlock();
            }
        }
    }
}

解法 3 - Semaphore

class FooBar {
    // 思路:
    // 2 个 Semaphore 分别控制
    private int n;
    Semaphore s1;
    Semaphore s2;

    public FooBar(int n) {
        this.n = n;
        this.s1 = new Semaphore(1);
        this.s2 = new Semaphore(0);
    }

    public void foo(Runnable printFoo) throws InterruptedException {
        
        for (int i = 0; i < n; i++) {
            s1.acquire();
        	printFoo.run();
            s2.release();
        }
    }

    public void bar(Runnable printBar) throws InterruptedException {
        
        for (int i = 0; i < n; i++) {
            s2.acquire();
        	printBar.run();
            s1.release();
        }
    }
}

解法 4 - LinkedBlockingQueue

class FooBar {
    // 思路:
    // 2 个 LinkedBlockingQueue 分别控制,用 SynchronousQueue 却超时,疑问
    private int n;
    BlockingQueue<Integer> queue1;
    BlockingQueue<Integer> queue2;

    public FooBar(int n) {
        this.n = n;
        this.queue1 = new LinkedBlockingQueue<>(1);
        try {
            queue1.put(1);
        } catch (Exception e) {}
        this.queue2 = new LinkedBlockingQueue<>(1);
    }

    public void foo(Runnable printFoo) throws InterruptedException {
        
        for (int i = 0; i < n; i++) {
            queue1.take();
        	printFoo.run();
            queue2.put(1);
        }
    }

    public void bar(Runnable printBar) throws InterruptedException {
        
        for (int i = 0; i < n; i++) {
            queue2.take();
        	printBar.run();
            queue1.put(1);
        }
    }
}

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