乐趣区

关于java:LeetCode1114-按序打印多线程-6种解法

作者:折纸
集体博客:https://www.zhezhi.press
记录菜鸡的成长之旅!

题目形容

咱们提供了一个类:

public class Foo {public void first() {print("first"); }
  public void second() { print("second"); }
  public void third() { print("third"); }
}

三个不同的线程 A、B、C 将会共用一个 Foo 实例。

  • 一个将会调用 first() 办法
  • 一个将会调用 second() 办法
  • 还有一个将会调用 third() 办法
    请设计批改程序,以确保 second() 办法在 first() 办法之后被执行,third()办法在 second() 办法之后被执行。

示例 1:

输出 : [1,2,3]
输入 : “firstsecondthird”
解释 :
有三个线程会被异步启动。
输出 [1,2,3] 示意线程 A 将会调用 first() 办法,线程 B 将会调用 second() 办法,线程 C 将会调用 third() 办法。
正确的输入是 “firstsecondthird”。

示例 2:

输出 : [1,3,2]
输入 : “firstsecondthird”
解释 :
输出 [1,3,2] 示意线程 A 将会调用 first() 办法,线程 B 将会调用 third() 办法,线程 C 将会调用 second() 办法。
正确的输入是 “firstsecondthird”。

提醒

  • 只管输出中的数字仿佛暗示了程序,然而咱们并不保障线程在操作系统中的调度程序。
  • 你看到的输出格局次要是为了确保测试的全面性。

话不多说 间接上代码,简略温习一下 Lock、synchronized、还有 CountDownLatch、Semaphore、CyclicBarrier 等工具类的应用

ReentrantLock + Condition

    class Foo {ReentrantLock lock = new ReentrantLock();
        Condition a = lock.newCondition();
        Condition b = lock.newCondition();
        Condition c = lock.newCondition();
        private volatile int status = 1;

        public Foo() {}

        public void first(Runnable printFirst) throws InterruptedException {
            

            try{lock.lock();
                while(status!=1){a.await();
                }
                status = 2;
                printFirst.run();
                b.signal();}finally{lock.unlock();
            }
            // printFirst.run() outputs "first". Do not change or remove this line.}

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

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

LockSupport

class Foo {
    static Thread aThread = null,bThread = null,cThread = null;
    private volatile int status = 1;
    public Foo() {}

    public void first(Runnable printFirst) throws InterruptedException {aThread = Thread.currentThread();
        printFirst.run();
        status = 2;
        LockSupport.unpark(bThread);
        // printFirst.run() outputs "first". Do not change or remove this line.
        // printFirst.run();}

    public void second(Runnable printSecond) throws InterruptedException {bThread = Thread.currentThread();
        while(status!=2)
            LockSupport.park();
        printSecond.run();
        status = 3;
        LockSupport.unpark(cThread);
        // printSecond.run() outputs "second". Do not change or remove this line.
        // printSecond.run();}

    public void third(Runnable printThird) throws InterruptedException {cThread = Thread.currentThread();
        while(status!=3)
            LockSupport.park();
        printThird.run();
        status = 1;
        LockSupport.unpark(aThread);
        // printThird.run() outputs "third". Do not change or remove this line.
        // printThird.run();}
}

synchronized + wait/notify

class Foo {Object lock = new Object();
    private volatile int status = 1;

    public Foo() {}

    public void first(Runnable printFirst) throws InterruptedException {synchronized(lock){while(status!=1){lock.wait();
            }
            printFirst.run();
            status = 2;
            lock.notifyAll();}
        // printFirst.run() outputs "first". Do not change or remove this line.}

    public void second(Runnable printSecond) throws InterruptedException {synchronized(lock){while(status!=2){lock.wait();
            }
            printSecond.run();
            status = 3;
            lock.notifyAll();}
        // printSecond.run() outputs "second". Do not change or remove this line.}

    public void third(Runnable printThird) throws InterruptedException {synchronized(lock){while(status!=3){lock.wait();
            }
            printThird.run();
            status = 1;
            lock.notifyAll();}
        // printThird.run() outputs "third". Do not change or remove this line.}
}

Semaphore

class Foo {Semaphore s = new Semaphore(1);
    private volatile int status = 1;

    public Foo() {}

    public void first(Runnable printFirst) throws InterruptedException {while(status!=1){ }
        s.acquire();
        // printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
        status = 2;
        s.release();}

    public void second(Runnable printSecond) throws InterruptedException {while(status!=2){ }
        s.acquire();
        // printFirst.run() outputs "first". Do not change or remove this line.
        printSecond.run();
        status = 3;
        s.release();
        // printSecond.run() outputs "second". Do not change or remove this line.}

    public void third(Runnable printThird) throws InterruptedException {while(status!=3){ }
        s.acquire();
        // printFirst.run() outputs "first". Do not change or remove this line.
        printThird.run();
        status = 1;
        s.release();
        
        // printThird.run() outputs "third". Do not change or remove this line.}
}

CountDownLatch

class Foo {CountDownLatch aLatch = new CountDownLatch(1);
    CountDownLatch bLatch = new CountDownLatch(1);


    public Foo() {}

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

    public void second(Runnable printSecond) throws InterruptedException {aLatch.await();//aLatch 计数器为 1,当线程 1 打印结束后 -- 为 0,这里不再被阻塞 线程 2 开始打印
        // printSecond.run() outputs "second". Do not change or remove this line.
        printSecond.run();
        bLatch.countDown();}

    public void third(Runnable printThird) throws InterruptedException {bLatch.await();//bLatch 计数器为 1,当线程 1 打印结束后 -- 为 0,这里不再被阻塞 线程 2 开始打印
        // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();}
}

CyclicBarrier

class Foo {CyclicBarrier cy1 = new CyclicBarrier(2);
    CyclicBarrier cy2 = new CyclicBarrier(2);

    public Foo() {}

    public void first(Runnable printFirst) throws InterruptedException {// printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
        try{cy1.await();
        }catch(BrokenBarrierException e){e.printStackTrace();
        }
    }

    public void second(Runnable printSecond) throws InterruptedException {
        try{cy1.await(); // 线程 1 曾经通过了 cy1 示意线程 1 曾经打印结束
// 当线程 1 和 2 都达到此处后 线程 2 才开始打印
            printSecond.run();
            cy2.await();// 线程 2 达到屏障 2}catch(BrokenBarrierException e){e.printStackTrace();
        }
        // printSecond.run() outputs "second". Do not change or remove this line.}

    public void third(Runnable printThird) throws InterruptedException {
        try{cy2.await();// 线程 2 打印结束后线程 3 才开始打印
            printThird.run();}catch(BrokenBarrierException e){e.printStackTrace();
        }
        // printThird.run() outputs "third". Do not change or remove this line.}
}
退出移动版