看了下leetcode,工作之后其实只刷了两百道左右,有一点怠惰。最近要疯狂刷题,练一下手感,记录一下各个题型的刷题记录。

多线程

  1. lettcode 1114 按序打印
    首先想到的就是使用信号量来解决:
class Foo {
    private Semaphore firsteSmaphore;
    private Semaphore secondSmaphore;
    private Semaphore thirdSmaphore;

    public Foo() {
        firsteSmaphore = new Semaphore(1);
        secondSmaphore = new Semaphore(0);
        thirdSmaphore = new Semaphore(0);
    }

    public void first(Runnable printFirst) throws InterruptedException {
        firsteSmaphore.acquire();
        // printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
        secondSmaphore.release();
    }

    public void second(Runnable printSecond) throws InterruptedException {
        secondSmaphore.acquire();
        // printSecond.run() outputs "second". Do not change or remove this line.
        printSecond.run();
        thirdSmaphore.release();
    }

    public void third(Runnable printThird) throws InterruptedException {
        thirdSmaphore.acquire();
        // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();
    }
}

代码也可以优化一下:

class Foo {

        private Semaphore semaphore12;
        private Semaphore semaphore23;


        public Foo() {
            semaphore12 = new Semaphore(0);
            semaphore23 = new Semaphore(0);
        }

        public void first(Runnable printFirst) throws InterruptedException {

            // printFirst.run() outputs "first". Do not change or remove this line.
            printFirst.run();
            semaphore12.release();
        }

        public void second(Runnable printSecond) throws InterruptedException {
            semaphore12.acquire();
            // printSecond.run() outputs "second". Do not change or remove this line.
            printSecond.run();
            semaphore23.release();
        }

        public void third(Runnable printThird) throws InterruptedException {
            semaphore23.acquire();
            // printThird.run() outputs "third". Do not change or remove this line.
            printThird.run();
        }
    }

还可以基于原子类来实现,其实本质上都是利用 AQS:

class Foo {

    private AtomicInteger firstAtomicInteger;
    private AtomicInteger secondAtomicInteger;
    public Foo() {
        firstAtomicInteger = new AtomicInteger(0);
        secondAtomicInteger = new AtomicInteger(0);
    }

    public void first(Runnable printFirst) throws InterruptedException {
        
        // printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
        firstAtomicInteger.incrementAndGet();
    }

    public void second(Runnable printSecond) throws InterruptedException {
        while(firstAtomicInteger.get() != 1) {
            // waiting
        }
        // printSecond.run() outputs "second". Do not change or remove this line.
        printSecond.run();
        secondAtomicInteger.incrementAndGet();
    }

    public void third(Runnable printThird) throws InterruptedException {
        while(secondAtomicInteger.get() != 1) {
            // waiting
        }
        // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();
    }
}

2. 1115 交替打印 FooBar

// 使用 Semaphore
class FooBar {
    private int n;
    private Semaphore fooSemaphore;
    private Semaphore barSemaphore;

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

    public void foo(Runnable printFoo) throws InterruptedException {
        
        for (int i = 0; i < n; i++) {
            fooSemaphore.acquire();
        	// printFoo.run() outputs "foo". Do not change or remove this line.
        	printFoo.run();
            barSemaphore.release();
        }
    }

    public void bar(Runnable printBar) throws InterruptedException {
        
        for (int i = 0; i < n; i++) {
            barSemaphore.acquire();
            // printBar.run() outputs "bar". Do not change or remove this line.
        	printBar.run();
            fooSemaphore.release();
        }
    }
}
// 使用阻塞队列
class FooBar {
    private int n;
    private BlockingQueue<Integer> fooBlockingQueue;
    private BlockingQueue<Integer> barBlockingQueue;

    public FooBar(int n) {
        this.n = n;
        fooBlockingQueue = new LinkedBlockingQueue<>(1);
        barBlockingQueue = new LinkedBlockingQueue<>(1);
    }

    public void foo(Runnable printFoo) throws InterruptedException {
        
        for (int i = 0; i < n; i++) {
            fooBlockingQueue.put(i);
        	// printFoo.run() outputs "foo". Do not change or remove this line.
        	printFoo.run();
            barBlockingQueue.put(i);
        }
    }

    public void bar(Runnable printBar) throws InterruptedException {
        
        for (int i = 0; i < n; i++) {
            barBlockingQueue.take();
            // printBar.run() outputs "bar". Do not change or remove this line.
        	printBar.run();
            fooBlockingQueue.take();
        }
    }
}

滑动窗口