zoukankan      html  css  js  c++  java
  • LeetCode:打印零与奇偶数【1116】

    LeetCode:打印零与奇偶数【1116】

    题目描述

    假设有这么一个类:

    class ZeroEvenOdd {
        public ZeroEvenOdd(int n) { ... }  // 构造函数
        public void zero(printNumber) { ... } // 仅打印出 0
        public void even(printNumber) { ... } // 仅打印出 偶数
        public void odd(printNumber) { ... } // 仅打印出 奇数
    }


    相同的一个 ZeroEvenOdd 类实例将会传递给三个不同的线程:

    • 线程 A 将调用 zero(),它只输出 0 。
    • 线程 B 将调用 even(),它只输出偶数。
    • 线程 C 将调用 odd(),它只输出奇数。

    每个线程都有一个 printNumber 方法来输出一个整数。请修改给出的代码以输出整数序列 010203040506... ,其中序列的长度必须为 2n。

    示例 1:

    输入:n = 2
    输出:"0102"
    说明:三条线程异步执行,其中一个调用 zero(),另一个线程调用 even(),最后一个线程调用odd()。正确的输出为 "0102"。
    示例 2:

    输入:n = 5
    输出:"0102030405"

    题目分析

      我们在1115题的时候已经说明,如果线程之间存在前驱关系的话可以用信号量来解决。我们先分析以下线程间的执行顺序:

      [打印0]——>[打印奇数]——>[打印0]——>[打印偶数]——>...

      可见,结果是2*n个数字,其中有n个零,剩下的就是奇数和偶数对半。于本题来说打印0是优先分配资源进行执行的,打印奇数和偶数都是受限制的。优先执行的结束后释放受限执行的线程的资源,受限线程才可继续执行,所以设置odd和even的资源初始值(即信号量)为0,每当零打印完成后,按照打印顺序为受限线程释放资源。odd和even执行完成后,需要释放打印零的资源,使得循环继续。

      一定要理解信号量,这是多线程编程的关键!!!

    Java题解

    import java.util.concurrent.*;
    
    class ZeroEvenOdd {
        private int n;
        private Semaphore s,s1,s2;
        
        
        public ZeroEvenOdd(int n) {
            this.n = n;
            s = new Semaphore(1);
            s1 = new Semaphore(0);
            s2 = new Semaphore(0);
        }
    
        // printNumber.accept(x) outputs "x", where x is an integer.
        public void zero(IntConsumer printNumber) throws InterruptedException {
            for(int i=1;i<=n;i++)
            {
                s.acquire();
                printNumber.accept(0);
                if((i&1) == 0)
                    s1.release();
                else
                    s2.release();
            }
        }
    
        public void even(IntConsumer printNumber) throws InterruptedException {
            for(int i=2;i<=n;i+=2)
            {
                s1.acquire();
                printNumber.accept(i);
                s.release();
            }
        }
    
        public void odd(IntConsumer printNumber) throws InterruptedException {
           for(int i=1;i<=n;i+=2)
            {
                s2.acquire();
                printNumber.accept(i);
                s.release();
            }
        }
    }
    

      

     

  • 相关阅读:
    HRMSYS项目源码分析(二)
    HRMSYS项目源码分析(一)
    SQL类型转换以及自动在前面补0满足10位工号标示法
    android—资源文件(res)的引用
    SQL serve创建与调用存储过程
    .wsdl文件生成.cs文件
    android 文件操作类简易总结
    android EncodingUtils
    FTP创建与操作
    如何调试框架中的app
  • 原文地址:https://www.cnblogs.com/MrSaver/p/11276275.html
Copyright © 2011-2022 走看看