面试手撕多线程(二)

多线程交替打印问题

例如:建立三个线程A、B、C,A线程打印10次字母A,B线程打印10次字母B,C线程打印10次字母C,但是要求三个线程同时运行,并且实现交替打印,即按照ABCABCABC的顺序打印。

Lock锁方法实现

  • 思路分析
    通过ReentrantLock我们可以很方便的进行显式的锁操作,即获取锁和释放锁,对于同一个对象锁而言,统一时刻只可能有一个线程拿到了这个锁,此时其他线程通过lock.lock()来获取对象锁时都会被阻塞,直到这个线程通过lock.unlock()操作释放这个锁后,其他线程才能拿到这个锁。
public class PrintABC {

    private int times;//控制打印的次数
    private int state; //控制当前的状态保证之间交替打印
    private Lock lock = new ReentrantLock();//保证每次只能一个线程能够拿到资源

    public PrintABC(int times) {
        this.times = times;
    }

    public void printA() {
        print("A", 0);
    }

    public void printB() {
        print("B", 1);
    }

    public void printC() {
        print("C", 2);
    }


    private void print(String name, int targetState) {
        for (int i = 0; i < times; ) {
            lock.lock();
            if (state % 3 == targetState) {
                state++;
                i++;
                System.out.println("线程:" + name + ",第 " + i + " 打印");
            }
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        PrintABC printABC = new PrintABC(10);
        new Thread(printABC::printA).start();
        new Thread(printABC::printB).start();
        new Thread(printABC::printC).start();

    }
}

使用Semaphore信号量实现

  • 思路分析
    直接使用 semaphore 中的 state 是否为1,为1时代表可执行。
public class PrintABC {
    private int times;
    private Semaphore semaphoreA = new Semaphore(1);
    private Semaphore semaphoreB = new Semaphore(0);
    private Semaphore semaphoreC = new Semaphore(0);

    public PrintABC(int times) {
        this.times = times;
    }


    public void printA() {
        try {
            print("A", semaphoreA, semaphoreB);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void printB() {
        try {
            print("A", semaphoreB, semaphoreC);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void printC() {
        try {
            print("A", semaphoreC, semaphoreA);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    private void print(String name, Semaphore current, Semaphore next) throws InterruptedException {
        for (int i = 0; i < times; i++) {
            current.acquire();
            System.out.println("线程:" + name + ",第 " + i + " 打印");
            next.release();
        }
    }

    public static void main(String[] args) {
        PrintABC printABC = new PrintABC(10);
        new Thread(printABC::printA).start();
        new Thread(printABC::printB).start();
        new Thread(printABC::printC).start();
    }
}

wait / notify 实现

  • 思路分析
    需要使用 synchronized 保证线程安全。

public class PrintABCUsingWaitNotify {
 
    private int times;
    private int state;
    private Object objectA = new Object();
    private Object objectB = new Object();
    private Object objectC = new Object();
 
    public PrintABCUsingWaitNotify(int times){
        this.times = times;
    }
 
    public void printA(){
        try {
            print("A", 0, objectA, objectB);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
 
    public void printB(){
        try {
            print("B", 1, objectB, objectC);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
 
    public void printC(){
        try {
            print("C", 2, objectC, objectA);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
 
    public void print(String name, int targetState, Object current, Object next) throws InterruptedException {
        for(int i = 0; i < times;){
            // 锁定当前线程
            synchronized(current){
                while(state % 3 != targetState){
                    current.wait();
                }
                state++;
                i++;
                System.out.println("线程:" + name + ",第 " + i + " 打印");
                synchronized(next){
                    // 通知下一个线程
                    next.notify();
                }
            }
        }
    }
 
    public static void main(String[] args) {
        PrintABCUsingWaitNotify printABC = new PrintABCUsingWaitNotify(10);
        new Thread(printABC::printA).start();
        new Thread(printABC::printB).start();
        new Thread(printABC::printC).start();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值