作者:折纸
集体博客: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.            }}