阿里真题:线程交叉打印

Posted 双斜杠少年

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了阿里真题:线程交叉打印相关的知识,希望对你有一定的参考价值。

leetcode 1115. 交替打印FooBar 多线程交替打印
五种方案实现多线程交替打印。

涉及 CyclicBarrier 篱栅、回环屏障 、Semaphore 信号灯、ReentrantLock、synchronized、AtomicBoolean 无锁cas 。

全部都已经在leetCode 提交通过

关于这些关键字的原理解释点我

代码如下:

ReentrantLock 方案

 /**
     * 方案3 ReentrantLock
     */
    class FooBar3 
        private int n;

        public FooBar3(int n) 
            this.n = n;
        

        ReentrantLock lock = new ReentrantLock(true);
        Condition c = lock.newCondition();
        volatile boolean flag = true;

        public void foo(Runnable printFoo) throws InterruptedException 

            for (int i = 0; i < n; i++) 
                lock.lock();
                try 
                    if (!flag) 
                        c.await();
                    
                    printFoo.run();
                    flag = false;
                    c.signal();
                 finally 
                    lock.unlock();
                
            
        

        public void bar(Runnable printBar) throws InterruptedException 
            for (int i = 0; i < n; i++) 
                lock.lock();
                try 
                    if (flag) 
                        c.await();
                    
                    printBar.run();
                    flag = true;
                    c.signal();
                 finally 
                    lock.unlock();
                
            
        
    

synchronized 方案

 /**
     * 方案4 与方案三同理 synchronized
     */
    class FooBar4 
        private int n;

        public FooBar4(int n) 
            this.n = n;
        

        volatile boolean flag = true;
        private final Object lock = new Object();

        public void foo(Runnable printFoo) throws InterruptedException 
            for (int i = 0; i < n; i++) 
                synchronized (lock) 
                    //首次执行放行
                    if (!flag) 
                        //当前线程挂起
                        lock.wait();
                    
                    flag = false;
                    printFoo.run();
                    lock.notifyAll();
                
            
        

        public void bar(Runnable printBar) throws InterruptedException 
            for (int i = 0; i < n; i++) 
                synchronized (lock) 
                    if (flag) 
                        //当前线程挂起
                        lock.wait();
                    
                    printBar.run();
                    flag = true;
                    lock.notifyAll();
                
            
        
    

AtomicBoolean 方案 CAS 无锁

/**
     * 方案5 无锁方案 cas
     */
    class FooBar5 
        private int n;

        public FooBar5(int n) 
            this.n = n;
        
        AtomicBoolean flag = new AtomicBoolean(true);
        public void foo(Runnable printFoo) throws InterruptedException 
            for (int i = 0; i < n; i++) 
                while (!flag.get()) 
                    Thread.yield();
                
                printFoo.run();
                flag.compareAndSet(true, false);
            
        

        public void bar(Runnable printBar) throws InterruptedException 
            for (int i = 0; i < n; i++) 
                while (flag.get()) 
                    Thread.yield();
                
                printBar.run();
                flag.compareAndSet(false, true);
            
        
    

Semaphore 方案 信号灯

 /**
     * 方案2 信号灯,相对简单
     */
    class FooBar2 
        private int n;

        public FooBar2(int n) 
            this.n = n;
        

        /**
         * semaphore初始化为1个信号量
         */
        private Semaphore semaphore = new Semaphore(1);
        /**
         * semaphore初始化为0个信号量
         */
        private Semaphore semaphore2 = new Semaphore(0);


        public void foo(Runnable printFoo) throws InterruptedException 

            for (int i = 0; i < n; i++) 
                //判断semaphore信号量是否存在
                semaphore.acquire();
                printFoo.run();
                //释放1个semaphore信号量
                semaphore2.release();
            
        

        public void bar(Runnable printBar) throws InterruptedException 

            for (int i = 0; i < n; i++) 

                //判断semaphore信号量是否存在
                semaphore2.acquire();
                printBar.run();
                //释放1个semaphore信号量
                semaphore.release();
            
        
    

CyclicBarrier 回环屏障

public class FooBar 
    private int n;

    public FooBar(int n) 
        this.n = n;
    

    private static final CyclicBarrier c = new CyclicBarrier(2);

    public void foo(Runnable printFoo) throws InterruptedException 

        for (int i = 0; i < n; i++) 

            // printFoo.run() outputs "foo". Do not change or remove this line.
            printFoo.run();
            try 
                c.await();
             catch (Exception e) 

            

        
    

    public void bar(Runnable printBar) throws InterruptedException 

        for (int i = 0; i < n; i++) 

            // printBar.run() outputs "bar". Do not change or remove this line.
            printBar.run();
            try 
                c.await();
             catch (Exception e) 

            
        
    


以上是关于阿里真题:线程交叉打印的主要内容,如果未能解决你的问题,请参考以下文章

Java 循环屏障

多线程高并发,三面蚂蚁金服(交叉面)定级阿里P6

三面蚂蚁金服(交叉面)定级阿里P6,已拿offer

阿里历年面试试题

阿里巴巴JAVA面试真题

Java学习教程!特殊渠道拿到阿里大厂面试真题