zoukankan      html  css  js  c++  java
  • c#随机数相关

    https://www.cnblogs.com/jackcheblog/p/7417632.html  这里列出几个常用但,效果一般的随机数生成方式;

    最大的陷阱可能还是来自我们的random

    上面的文章,写的很一般,很一般;

    具体的还是看我们c# in depth 中的一篇关于random的文章;http://csharpindepth.com/Articles/Chapter12/Random.aspx

    The parameterless constructor for Random takes the current date and time as the seed

    然后,我再写一些完整的测试代码;

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication70
    {
    
        /// <summary>
        /// 错误的单例模式;
        /// </summary>
        public static class RandomHelper
        {
            //这样的话,能够保证,高并发下的单例=》Random,但是不能保证,高并发下的时间搓,也就是我们的seed子不同;
            //所以这种做法依然有一定的风险;
            //这样写,智能保证 random 在 RandomHelper 中是线程安全的;
            private static Random random;
            private static readonly object _locker = new object();//低并发的情况下,用lock,简单粗暴,不出错
    
            public static Random GetThreadSafeRandom
            {
                get
                {
                    if (random == null)
                    {
                        lock (_locker)
                        {
                            if (random == null)
                            {
                                return new Random();  //不存在每次都生成一个实例;错误
                            }
                        }
                    }
                    return random;
                }
            }
        }
    
    
        /// <summary>
        /// 正确的单例模式;
        /// </summary>
        public static class RandomHelperV1
        {
            //这样的话,能够保证,高并发下的单例=》Random,但是不能保证,高并发下的时间搓,也就是我们的seed子不同;
            //所以这种做法依然有一定的风险;
            //这样写,智能保证 random 在 RandomHelper 中是线程安全的;
            private static Random random;
            private static readonly object _locker = new object();//低并发的情况下,用lock,简单粗暴,不出错
    
            public static Random GetThreadSafeRandom
            {
                get
                {
                    if (random == null)
                    {
                        lock (_locker)
                        {
                            if (random == null)
                            {
                                random= new Random();  //不存在每次都生成一个实例;错误
                                return random;
                            }
                        }
                    }
                    return random;
                }
            }
        }
    
    
    
        /// <summary>
        /// 也就是要解决两个问题;一个是for循环,生成的是相同的实例;因为seed是基于本机系统的事件;使用同一个seed,生词的随机数就是一样滴呀;
        /// 第二个就是在高并发下,
        /// </summary>
        class Program
        {
            /// <summary>
            /// 关于random 经典的问题;
            /// </summary>
            static void Test0()
            {
                for (int i = 0; i < 10; i++)
                {
                    Random random = new Random();
                    int result= random.Next(0,10);  //重复,非随机; 最本质的问题,还是,系统时间的问题;
                    Console.WriteLine(result);
                }
            }
    
            /// <summary>
            /// 单例模式能够解决问题吗? 这个只是为了记录一下:错误的单例模式写法;
            /// 窝草,单例模式,用错了;窝草;
            /// </summary>
            static void Test1()
            {
                
                for (int i = 0; i < 10; i++)
                {
                    int result=RandomHelper.GetThreadSafeRandom.Next(0,10); //虽然只有一个实例,但是还是生产了重复的东西;
                    //调用方法是对的,是我们的单例模式的实现错了;
                    Console.WriteLine(result);
                }
    
            }
    
            /// <summary>
            /// 这样能解决问题;but web 天生多线程;能够保证在多线程下,不会生成同一个random吗?
            /// </summary>
            static void Test11()
            {
                Random random = new Random(); //确保random先初始化
                for (int i = 0; i < 10; i++)
                {
                    int result = random.Next(0, 10); 
                    Console.WriteLine(result);
                }
            }
    
            
    
            /// <summary>
            ///  采用单例模式,but=>这样就利用到lock,保证了多线程单例,但是,并发性就降低了;
            ///  有没有更好的解决方案呢;
            /// </summary>
            static void Test2()
            {
                for (int i = 0; i < 10; i++)
                {
                    int result = RandomHelperV1.GetThreadSafeRandom.Next(0, 10); //虽然只有一个实例,但是还是生产了重复的东西;
                    Console.WriteLine(result);
                }
            }
    
           static void TestTick()
            {
                for (int i = 0; i < 10; i++)
                {
                    int result = Environment.TickCount;
                    Thread.Sleep(1);
                    Console.WriteLine(result);
                }
            }
    
            /// <summary>
            /// 第一次重视错误的;
            /// </summary>
            static void TestRandomTick()
            {
                int _seed=Environment.TickCount; //这样做也是于是舞步滴呀;
                for (int i = 0; i < 10; i++)
                    {
                         //int _seed=Environment.TickCount; //这样做也是于是舞步滴呀;
                         Random random = new Random(Interlocked.Increment(ref _seed));
                         int result = random.Next(0, 10);  //重复,非随机; 最本质的问题,还是,系统时间的问题;
                        Console.WriteLine(result);
                    }
            }
    
            static void TestRandomCount()
            {
                for (int i = 0; i < 10; i++)
                {
                    Random random = new Random(i);//每次输入不同的种子;保证每一次的种子不一样;
                    int result = random.Next(0, 10);  
                    Console.WriteLine(result);
                }
            }
    
            static void Main(string[] args)
            {
    
                Console.WriteLine("--------------------test0");
                Test0();
                Thread.Sleep(100);
                Console.WriteLine("--------------------test1");
                Test1();
                Console.WriteLine("--------------------test11");
                Test11();
                //Thread.Sleep(100); //这样的话,Test11 和 Test2 生成了相同的随机数;窝草;
                Console.WriteLine("--------------------test2");
                Test2();
                Console.WriteLine("--------------------TestTick");
                TestTick();
                Console.WriteLine("--------------------TestRandomTick");
                TestRandomTick();
                Console.WriteLine("--------------------TestRandomCount");
                TestRandomCount();
    
               //to be continuted....
                Console.ReadLine();
    
    
    
    
            }
        }
    }

    然后,较好的一种解决方案;

        /// <summary>
        /// 随机数提供者
        /// 保证每个线程使用自身的随机数产生器
        /// </summary>
        public static class RandomProvider
        {
            private static int _seed = Environment.TickCount;
    
            private static readonly ThreadLocal<Random> RandomWrapper = new ThreadLocal<Random>(() =>
                new Random(Interlocked.Increment(ref _seed))
            );
    
            /// <summary>
            /// 获取线程相关的随机数产生器
            /// </summary>
            /// <returns></returns>
            public static Random GetThreadRandom()
            {
                return RandomWrapper.Value;
            }
        }

    to do list....

  • 相关阅读:
    Java语法基础-final关键字
    Java语法基础-异常处理
    Java语法基础-序列化
    Java的知识储备及面试-几个方面
    一篇分析测试开发人员的职业发展方向的好文章-学习笔记
    web 自动化测试 selenium基础到应用(目录)
    打包Scala jar 包的正确步骤
    IT项目管理
    寄存器 & 汇编指令
    Window环境下编写Shellcode(入门篇)
  • 原文地址:https://www.cnblogs.com/mc67/p/7988926.html
Copyright © 2011-2022 走看看