• 爱奇艺笔试题 输出01020304... ...


    简介

    三个线程一个线程输出0, 一个线程输出奇数, 还有一个线程输出偶数, 下面的代码感觉逻辑挺乱的.

    code

    import java.util.Scanner;
    import java.util.concurrent.Semaphore;
    import java.util.function.IntConsumer;
    
    public class Main {
        public static void main(String[] args) {
            final Scanner reader = new Scanner(System.in);
            int n = reader.nextInt();
    
            ZeroEvenOdd zeroEvenOdd = new ZeroEvenOdd(n);
            new Thread(() -> {
                try {
                    zeroEvenOdd.printZero(System.out::print);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
            new Thread(() -> {
                try {
                    zeroEvenOdd.printEven(System.out::print);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
            new Thread(() -> {
                try {
                    zeroEvenOdd.printOdd(System.out::print);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
    
    class ZeroEvenOdd {
        private int n;
    
        volatile int t;
        volatile boolean b;
        volatile boolean c;
        public ZeroEvenOdd(int n) {
            this.n = n;
            t = n;
            b = false;
            c = false;
        }
    
        // printNumber.accept(x) outputs "x", where x is an integer.
        public  void  printZero(IntConsumer printNumber) throws InterruptedException {
            while(n > 0) {
                synchronized (this) {
                    if(b == false) {
                        if(t!=n && t!=(n+1)) // 为什么要这么写呢, 首先比如输入n=5那么, 输出奇数他会首先输出1个0, 所以屏蔽, 然后奇数线程会获得执行然后输出1,然后他又获得执行权输出0
                            System.out.print(0);
                        b = true;
                    }
                }
    
            }
        }
    
        public  void printEven(IntConsumer printNumber) throws InterruptedException {
            while(n > 0) {
                synchronized (this){
                    if(b == true) {
                            if(n %2 ==0) {
                                System.out.print(t-n);
                                n--;
                                b = false;
                            }
                        }
                }
            }
        }
    
        public  void printOdd(IntConsumer printNumber) throws InterruptedException {
            while(n > 0) {
                    synchronized (this) {
                        if(b == true) {
                            if (n % 2 != 0) {
                                System.out.print(t - n); // 这里会输出第一个0
                                n--;
                                b = false;
                            }
                        }
                    }
            }
    
    
        }
    
    
    }
    

    TIPS

    逻辑上应该使用信号量, 因为信号量的使用场景就是这样子的. 顺序对于资源的把控

    class AlternatePrinting {
    
    
        public static void main(String[] args) throws InterruptedException {
    
            Semaphore semaphoreOld = new Semaphore(1);
            Semaphore semaphoreEven = new Semaphore(1);
    
            semaphoreOld.acquire();//让奇数先启动,所以先减掉偶数的信号量 等奇数线程来释放
    
            SemaphorePrintEven semaphorePrintEven = new SemaphorePrintEven(semaphoreOld, semaphoreEven);
            Thread t1 = new Thread(semaphorePrintEven);
            t1.start();
    
            SemaphorePrintOdd semaphorePrintOdd = new SemaphorePrintOdd(semaphoreOld, semaphoreEven);
            Thread t2 = new Thread(semaphorePrintOdd);
            t2.start();
    
        }
    
        /**
         * 使用信号量实现
         */
        static class SemaphorePrintOdd implements Runnable {
    
            int i = 0;
            private Semaphore semaphoreOdd;
            private Semaphore semaphoreEven;
    
    
            public SemaphorePrintOdd(Semaphore semaphoreOdd, Semaphore semaphoreEven) {
                this.semaphoreOdd = semaphoreOdd;
                this.semaphoreEven = semaphoreEven;
            }
    
            @Override
            public void run() {
                try {
                    semaphoreOdd.acquire();//获取信号量
                    while (true) {
                        i++;
                        if (i % 2 == 0) {
                            System.out.println("偶数线程:" + i);
                            semaphoreEven.release();
                            //再次申请获取偶数信号量,因为之前已经获取过,如果没有奇数线程去释放,那么就会一直阻塞在这,等待奇数线程释放
                            Thread.sleep(300);
                            semaphoreOdd.acquire();
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
        static class SemaphorePrintEven implements Runnable {
    
            int i = 0;
            private Semaphore semaphoreOdd;
            private Semaphore semaphoreEven;
    
    
            public SemaphorePrintEven(Semaphore semaphoreOdd, Semaphore semaphoreEven) {
                this.semaphoreOdd = semaphoreOdd;
                this.semaphoreEven = semaphoreEven;
            }
    
            @Override
            public void run() {
    
                try {
                    semaphoreEven.acquire();
                    while (true) {
                        i++;
                        if (i % 2 == 1) {
                            System.out.println("奇数线程:" + i);
                            semaphoreOdd.release();
                            semaphoreEven.acquire();//再次申请获取奇数信号量,需要等偶数线程执行完然后释放该信号量,不然阻塞
                        }
                    }
    
                } catch (Exception ex) {}
    
    
            }
        }
    }
    
    
    Hope is a good thing,maybe the best of things,and no good thing ever dies.----------- Andy Dufresne
  • 相关阅读:
    css display和vertical-align 属性
    Python:time模块/random模块/os模块/sys模块
    css display和vertical-align 属性
    初始面向对象
    模块小记
    迭代器与生成器
    默认参数的陷阱自我心得
    初始函数
    文件操作
    python基础知识补充
  • 原文地址:https://www.cnblogs.com/eat-too-much/p/15173803.html
Copyright © 2020-2023  润新知