【面试系列】多线程面试题2

180 阅读1分钟

题目:两个线程交替打印,线程 1 打印 A-Z,线程 2 打印 1-26。最终结果 A 1 B 2 ... Z 26。

下面给出 4 种解法

等待通知机制

synchronized

public class PrintOrderByOrderWithWaitAndNotify {

    public static void main(String[] args) {

        Object lock = new Object();

        // 先启动t2
        new Thread(() -> {
            for (int i = 1; i <= 26; i++) {
                synchronized (lock) {
                    // 先阻塞自己
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.print(i + " ");
                    // 唤醒t1
                    lock.notify();
                }
            }

        }, "t2").start();

        // 后启动t1
        new Thread(() -> {
            for (int i = 0; i < 26; i++) {
                synchronized (lock) {
                    System.out.print((char) (65 + i) + " ");
                    // 唤醒t2
                    lock.notify();
                    try {
                        // 提前释放锁,让t2执行,否则需要等到t1的所有代码执行完才会释放锁
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }, "t1").start();
    }
}

Condition

public class PrintOrderByOrderWithCondition {

    public static void main(String[] args) {

        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();

        // 先启动t2
        new Thread(() -> {
            for (int i = 1; i <= 26; i++) {
                lock.lock();
                try {
                    // 先阻塞自己
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.print(i + " ");
                    // 唤醒t1
                    condition.signal();
                } finally {
                    lock.unlock();
                }
            }
        }, "t2").start();

        // 后启动t1
        new Thread(() -> {
            for (int i = 0; i < 26; i++) {
                lock.lock();
                try {
                    System.out.print((char) (65 + i) + " ");
                    // 唤醒t2
                    condition.signal();
                    try {
                        // 提前释放锁,让t2执行,否则需要等到t1的所有代码执行完才会释放锁
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } finally {
                    lock.unlock();
                }
            }
        }, "t1").start();
    }
}

CyclicBarrier + Semaphore

public class PrintOrderByOrderWithCyclicBarrierAndSemaphore {

    public static void main(String[] args) {

        CyclicBarrier barrier = new CyclicBarrier(2);
        Semaphore semaphore = new Semaphore(1);

        new Thread(() -> {
            for (int i = 0; i < 26; i++) {
                // 获取许可证
                try {
                    semaphore.acquire();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 打印
                System.out.print((char) (65 + i) + " ");
                // 等待
                try {
                    barrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }
        }, "t1").start();

        new Thread(() -> {
            for (int i = 1; i <= 26; i++) {
                // 破坏屏障
                try {
                    barrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
                // 打印
                System.out.print(i + " ");
                // 释放许可证
                semaphore.release();
            }

        },"t2").start();
    }
}

LockSupport

public class PrintOrderByOrderWithLockSupport {

    static Thread t1 = null, t2 = null;

    public static void main(String[] args) {

        t1 = new Thread(() -> {
            for (int i = 0; i < 26; i++) {
                System.out.print((char) (65 + i) + " ");
                // 先唤醒t2
                LockSupport.unpark(t2);
                // 然后阻塞t1自己
                LockSupport.park();
            }
        });

        t2 = new Thread(() -> {
            for (int i = 1; i <= 26; i++) {
                // 阻塞t2自己
                LockSupport.park();
                System.out.print(i + " ");
                // t2结束以后唤醒t1
                LockSupport.unpark(t1);
            }
        });

        t2.start();
        t1.start();

    }
}