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....

  • 相关阅读:
    HDU 2955 Robberies(01背包)
    HDU 2602 Bone Collector(01背包)
    HUST 1352 Repetitions of Substrings(字符串)
    HUST 1358 Uiwurerirexb jeqvad(模拟解密)
    HUST 1404 Hamming Distance(字符串)
    HDU 4520 小Q系列故事――最佳裁判(STL)
    HDU 2058 The sum problem(枚举)
    【破解】修改程序版权、添加弹窗
    HDU 1407 测试你是否和LTC水平一样高(枚举)
    HDU 1050 Moving Tables(贪心)
  • 原文地址:https://www.cnblogs.com/mc67/p/7988926.html
Copyright © 2011-2022 走看看