Leetcode 1144

今天做了一个Leetcode题很有意思,有别于其他算法题,这是一个跟多线程相关的题,首先看一下题目:

我们提供了一个类:

public class Foo {
  public void one() { print("one"); }
  public void two() { print("two"); }
  public void three() { print("three"); }
}
三个不同的线程将会共用一个 Foo 实例。

线程 A 将会调用 one() 方法
线程 B 将会调用 two() 方法
线程 C 将会调用 three() 方法
请设计修改程序,以确保 two() 方法在 one() 方法之后被执行,three() 方法在 two() 方法之后被执行。

这个题目的关键一目了然,就是如何保证三个线程按照指定的顺序去依次执行,即先执行A,然后B,最后C。

方法一

类似于cas自旋:

class Foo {
    private volatile int a = 1;
    
    public Foo() {
        
    }

    public void first(Runnable printFirst) throws InterruptedException {
        
        // printFirst.run() outputs "first". Do not change or remove this line.
        for(;;)
        {
            if(a==1)
            {
                printFirst.run();
                a = 2;
                break;
            }
        } 
    }

    public void second(Runnable printSecond) throws InterruptedException {
        
        // printSecond.run() outputs "second". Do not change or remove this line.
        for(;;)
        {
            if(a==2)
            {
                printSecond.run();
                a = 3;
                break;
            }
        }     
    }

    public void third(Runnable printThird) throws InterruptedException {
        
        // printThird.run() outputs "third". Do not change or remove this line.
        for(;;)
        {
            if(a==3)
            {
                printThird.run();
                a = 1;
                break;
            }
        }                   
    }
}

方法二

使用关键字synchronized以及方法wait()和notify(),相当于设置了两道屏障:

class Foo {
    boolean first_finished = false;
    boolean second_finished = false;
    Object lock = new Object();

    public Foo() {
        
    }

    public void first(Runnable printFirst) throws InterruptedException {
        
        // printFirst.run() outputs "first". Do not change or remove this line.
        synchronized(lock)
        {
            printFirst.run();
            first_finished = true;
            lock.notifyAll();
        }
        
    }

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

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

方法三

使用CountDownLatch这个类,用来计数需要等待线程的数量。

class Foo {
    private CountDownLatch cnt_A = new CountDownLatch(1);
    private CountDownLatch cnt_B = 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();
        cnt_A.countDown();
    }

    public void second(Runnable printSecond) throws InterruptedException {
        
        // printSecond.run() outputs "second". Do not change or remove this line.
        cnt_A.await();
        printSecond.run();
        cnt_B.countDown();
    }

    public void third(Runnable printThird) throws InterruptedException {
        
        // printThird.run() outputs "third". Do not change or remove this line.
        cnt_B.await();
        printThird.run();
    }
}
发布了34 篇原创文章 · 获赞 80 · 访问量 2016

猜你喜欢

转载自blog.csdn.net/jackzhang11/article/details/102879551