LeetCode 1114:按序打印

题目描述

给你一个类:

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

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

  • 线程 A 将会调用 first() 方法
  • 线程 B 将会调用 second() 方法
  • 线程 C 将会调用 third() 方法

请设计修改程序,以确保 second() 方法在 first() 方法之后被执行,third() 方法在 second() 方法之后被执行。

解题思路

本文重点介绍Semaphore的两个变种解法,第一种是常规接发,相当于3个线程,有一个充当主线程做if else判断,其他执行线程满足if条件执行acquire时,因为Semaphore变量为0所以会停止等待,等待类主线程执行release后,完成相应Semaphore的+1操作,对应线程可继续执行打印输出。最后不要忘记对在支路线程中对主线程的Semaphore进行release的+1操作,便于后续其他线程执行相似操作。
Semaphore的法二则更加简洁巧妙,原理也是按顺序一个线程先执行acquire,Semaphore为0时等待停止,后续对下一个Semaphore进行release,相当于通知下一个等待中的线程可以继续执行,以此来控制线程的打印顺序。

代码实现

Synchronized

class Foo {
    private int i = 1;
    private int n = 3;


    public Foo() {
        
    }

    public void first(Runnable printFirst) throws InterruptedException {
        while(i <= n){
            synchronized(this){
                if(i <= n && i % 3 == 1){
                    printFirst.run();
                    i++;
                }
            }
        }
        
    }

    public void second(Runnable printSecond) throws InterruptedException {
        while(i <= n){
            synchronized(this){
                if(i <= n && i % 3 == 2){
                    printSecond.run();
                    i++;
                }
            }
        }
    }

    public void third(Runnable printThird) throws InterruptedException {
        while(i <= n){
            synchronized(this){
                if(i <= n && i % 3 == 0){
                    printThird.run();
                    i++;
                }
            }
        }
    }
}

ReentrantLock

class Foo {
    private int i = 1;
    private int n = 3;

    private Lock lock = new ReentrantLock();

    public Foo() {
        
    }

    public void first(Runnable printFirst) throws InterruptedException {
        while(i <= n){
            lock.lock();
            try{
                if(i <= n && i % 3 == 1){
                    printFirst.run();
                    i++;
                }
            }finally{
                lock.unlock();
            }
        }
        
    }

    public void second(Runnable printSecond) throws InterruptedException {
        while(i <= n){
            lock.lock();
            try{
                if(i <= n && i % 3 == 2){
                    printSecond.run();
                    i++;
                }
            }finally{
                lock.unlock();
            }
        }
    }

    public void third(Runnable printThird) throws InterruptedException {
        while(i <= n){
            lock.lock();
            try{
                if(i <= n && i % 3 == 0){
                    printThird.run();
                    i++;
                }
            }finally{
                lock.unlock();
            }
        }
    }
}

CyclicBarrier

class Foo {
    private int i = 1;
    private int n = 3;

    private CyclicBarrier cb = new CyclicBarrier(3);

    public Foo() {
        
    }

    public void first(Runnable printFirst) throws InterruptedException {
        
        for(int i = 1;i <= n ;i++){
            if(i<= n && i % 3 == 1){
                printFirst.run();
            }
            try{
                cb.await();
            }catch(BrokenBarrierException e){
                e.printStackTrace();
            }
        }
        
        
    }

    public void second(Runnable printSecond) throws InterruptedException {
        
        for(int i = 1;i <= n ;i++){
            if(i<= n && i % 3 == 2){
                printSecond.run();
            }
            try{
                cb.await();
            }catch(BrokenBarrierException e){
                e.printStackTrace();
            }
        }
        
    }

    public void third(Runnable printThird) throws InterruptedException {
    
        for(int i = 1;i <= n ;i++){
            if(i<= n && i % 3 == 0){
                printThird.run();
            }
            try{
                cb.await();
            }catch(BrokenBarrierException e){
                e.printStackTrace();
            }
        }
        
    }
}

Semaphore法一

class Foo {
    private int i = 1;
    private int n = 3;

    private Semaphore semaphore1 = new Semaphore(0);
    private Semaphore semaphore2 = new Semaphore(0);
    private Semaphore semaphore3 = new Semaphore(1);

    public Foo() {
        
    }

    public void first(Runnable printFirst) throws InterruptedException {
        while(i <= n){
            if(i<= n && i % 3 == 1){
                semaphore1.acquire();
                printFirst.run();
                i++;
                semaphore3.release();
            }
        }   
    }

    public void second(Runnable printSecond) throws InterruptedException {
        while(i <= n){
            if(i<= n && i % 3 == 2){
                semaphore2.acquire();
                printSecond.run();
                i++;
                semaphore3.release();
            }
        }   
    }

    public void third(Runnable printThird) throws InterruptedException {
        while(i <= n){
            semaphore3.acquire();
            if(i<= n && i % 3 == 0){
                printThird.run();
                i++;
                semaphore3.release();
            }else if(i<= n && i % 3 == 1){
                semaphore1.release();
            }else if(i<= n && i % 3 == 2){
                semaphore2.release();
            }
        }   
    }
}

Semaphore法二

class Foo {
    private int i = 1;
    private int n = 3;

    private Semaphore semaphore12 = new Semaphore(0);
    private Semaphore semaphore23 = new Semaphore(0);


    public Foo() {
        
    }

    public void first(Runnable printFirst) throws InterruptedException {
        printFirst.run();
        semaphore12.release();

    }

    public void second(Runnable printSecond) throws InterruptedException {
        semaphore12.acquire();
        printSecond.run();
        semaphore23.release();
    }

    public void third(Runnable printThird) throws InterruptedException {
       semaphore23.acquire();
       printThird.run();
    }
}

总结

本题来源于Leetcode中 归属于多线程类型题目。
同许多在算法道路上不断前行的人一样,不断练习,修炼自己!
如有博客中存在的疑问或者建议,可以在下方留言一起交流,感谢各位!

觉得本博客有用的客官,可以给个赞鼓励下! 嘿嘿

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值