循环依赖的解决办法_随机播放歌曲并不随机?内含硬核解决办法!

bdde7589a1519312e99b0b25bd71340a.png

点击菜单栏“阅读打卡”

发现更多精彩和惊喜

周末,开车带女朋友出去玩,车里面,随机播放着周杰伦的歌曲。我正沉浸在『得儿飘,得儿飘,得儿意的飘』中,幻想着自己是秋名山车神,突然,旁边的女朋友说话了。

诶,你车上的歌曲是随机播放的吗?

cbf618a272a399810a99b29b3895e1d8.png

是啊

df4504d3574e7e5477cd82f935d52bf0.png

那为什么听来听去反反复复都是那么几首歌在重复啊。 

bd3afde23d37cdd3fd0b2e8a0485d79a.png

嗯,音乐随机播放用的是伪随机算法呗。

df4504d3574e7e5477cd82f935d52bf0.png

伪随机性(英语:Pseudorandomness)是一个过程似乎是随机的,但实际上并不是。伪随机数是看似随机实质是固定的周期性序列,也就是有规则的随机。

又拽概念了,你给我详细讲讲吧。

df4504d3574e7e5477cd82f935d52bf0.png

好的,等到了前面的服务区,我给你讲讲。

df4504d3574e7e5477cd82f935d52bf0.png

什么是随机数

随机数在计算机应用中使用的比较广泛,最为熟知的便是在密码学中的应用。随机数有3个特性,具体如下:

随机性:不存在统计学偏差,是完全杂乱的数列

不可预测性:不能从过去的数列推测出下一个出现的数

不可重现性:除非将数列本身保存下来,否则不能重现相同的数列

音乐播放器的随机播放如何实现的

现在的音乐播放器都比较智能了,都带有一些类似于歌曲推荐的功能,会给听众随机推荐歌曲,这种是基于用户听歌习惯的随机推荐,不在我们讨论的范围内。我们只讨论那种简单的,比如使用简单的播放器随机播放一个CD卡中的列表的情况。

常见的音乐随机播放算法有两种,分别是Random算法和Shuffle算法。

Random算法

Random算法相对比较简单,播放当前歌曲时才随机生成下一曲。

Random算法是在选取即将播放的歌曲时,进行一个随机数的运算,得到即将播放的歌曲在播放列表中的索引,播放列表本身并没有被打乱,只是利用随机函数从播放列表中选取一首歌曲进行播放而已。

可以使用Java语言实现这种Random随机数算法:

Calendar ca = Calendar.getInstance();//获取系统当前时间int i;
Random rand =new Random(ca.get(Calendar.MINUTE)*ca.get(Calendar.SECOND));//将随机数的种子设置为当前系统时间的分*秒
i=rand.nextInt(maxnum);//maxnum是随机数最大不超过得值

Random算法另一个缺陷是当点击“上一曲”时,跟“下一曲”功能完全一样,都是重新生成随机数,并利用它从播放列表中选取歌曲进行播放,而不会回到刚刚播放的那一首歌。

这种方法不好,都没办法找到上一首了。

da0b57bb830b83c6788a5dbea6a63141.png

其实也有解决办法,比如提供个历史纪录来弥补。

df4504d3574e7e5477cd82f935d52bf0.png

太麻烦了吧。还有另外的算法吗?

da0b57bb830b83c6788a5dbea6a63141.png

有的,那就是洗牌算法。

df4504d3574e7e5477cd82f935d52bf0.png

Shuffle算法

Shuffle算法和排序算法正好相反,是从有序到乱序的一个过程,俗称洗牌算法。

它将播放列表中的歌曲顺序打乱,变成一个和原来歌曲顺序没有任何关系的乱序的播放列表,之后进行歌曲的播放,并支持当用户点击“上一首”时,能够回到刚刚播放的那一首歌曲。

这种算法相对于Random算法来说,并不是完全意义上的随机,只不过是对歌曲列表的乱序而已,歌曲的播放顺序还是相对固定的。

在Java中,有现成的shuffle算法实现,即Collections类中的两个重载的shuffle方法:

public static void shuffle(List> list) {
    Random rnd = r;if (rnd == null)
        r = rnd = new Random();
    shuffle(list, rnd);
}private static Random r;public static void shuffle(List> list, Random rnd) {int size = list.size();if (size list instanceof RandomAccess) {
        for (int i=size; i>1; i--)
            swap(list, i-1, rnd.nextInt(i));
    } else {
        Object arr[] = list.toArray();

        // Shuffle array
        for (int i=size; i>1; i--)
            swap(arr, i-1, rnd.nextInt(i));

        // Dump array back into list
        ListIterator it = list.listIterator();
        for (int i=0; i            it.next();
            it.set(arr[i]);
        }
    }
}

哦,那我们的播放器应该是使用Shuffle实现的吧。

bd3afde23d37cdd3fd0b2e8a0485d79a.png

嗯,我们每次听的歌曲顺序几乎都一致,表现上比较像。

df4504d3574e7e5477cd82f935d52bf0.png

那我们这个就是伪随机,如果使用Random就是真随机了。

df4504d3574e7e5477cd82f935d52bf0.png

不是的。这是不同的概念。

df4504d3574e7e5477cd82f935d52bf0.png

真随机与伪随机

随机数分为真随机数和伪随机数,我们程序使用的基本都是伪随机数,其中伪随机又分为强伪随机数和弱伪随机数。

  • 真随机数,通过物理实验得出,比如掷钱币、骰子、转轮、使用电子元件的噪音、核裂变等。需要满足随机性、不可预测性、不可重现性。

  • 伪随机数,通过一定算法和种子得出。软件实现的是伪随机数。

    • 强伪随机数,难以预测的随机数。需要满足随机性和不可预测性。

    • 弱伪随机数,易于预测的随机数。需要满足随机性。

上面介绍Random算法和Shuffle算法的时候,代码实现都是伪随机算法。可以这样说:

只要这个随机数是由确定算法生成的,那就是伪随机只能通过不断算法优化,使你的随机数更接近随机。

有限状态机不能产生真正的随机数的,所以,现代计算机中,无法通过一个纯算法来生成真正的随机数,无论是哪种语言,单纯的算法生成的数字都是伪随机数,都是由可确定的函数通过一个种子,产生的伪随机数。

这也就意味着,如果知道了种子,就可以推断接下来的随机数序列的信息。这就有了可预测性。

那么真随机数怎么产生的呢?

通过真实随机事件取得的随机数才是真随机数。

真正的随机数是使用物理现象产生的:比如掷钱币、骰子、转轮、使用电子元件的噪音、核裂变等等。这样的随机数发生器叫做物理性随机数发生器,它们的缺点是技术要求比较高,效率低。

现有的真随机数生成器,比如PuTTYgen的随机数是让用户移动鼠标达到一定的长度,之后把鼠标的运动轨迹转化为种子;Intel通过电阻和振荡器来生成热噪声作为信息熵资源;Unix/Linux的dev/random和/dev/urandom采用硬件噪音生成随机数;

所以,要想生成真的随机数,是无法用任何一个纯算法实现的。都需要借助外部物理现象。

啊?这也太难了吧,想要生成个随机数,竟然还要懂物理学。

da0b57bb830b83c6788a5dbea6a63141.png

是的。确定性的算法生成的随机数,至少都有可重现性。那就不是真随机数了。

df4504d3574e7e5477cd82f935d52bf0.png

那你们平时工作重要使用随机数怎么办啊?

cbf618a272a399810a99b29b3895e1d8.png

这就要看场景了,一般使用伪随机数就可以解决问题了。

df4504d3574e7e5477cd82f935d52bf0.png

Java中的随机数生成器

Java语言提供了几种随机数生成器,如前面提到的Random类,还有SecureRandom类。

伪随机数生成器

伪随机数发生器采用特定的算法,将随机数种子seed转换成一系列的伪随机数。伪随机数依赖于seed的值,给定相同的seed值总是生成相同的随机数。伪随机数的生成过程只依赖CPU,不依赖任何外部设备,生成速度快,不会阻塞。

Java提供的伪随机数发生器有java.util.Random类和java.util.concurrent.ThreadLocalRandom类。

Random类采用AtomicLong实现,保证多线程的线程安全性,但正如该类注释上说明的,多线程并发获取随机数时性能较差。

多线程环境中可以使用ThreadLocalRandom作为随机数发生器,ThreadLocalRandom采用了线程局部变量来改善性能,这样就可以使用long而不是AtomicLong,此外,ThreadLocalRandom还进行了字节填充,以避免伪共享。

强随机数发生器

强随机数发生器依赖于操作系统底层提供的随机事件。强随机数生成器的初始化速度和生成速度都较慢,而且由于需要一定的熵累积才能生成足够强度的随机数,所以可能会造成阻塞。熵累积通常来源于多个随机事件源,如敲击键盘的时间间隔,移动鼠标的距离与间隔,特定中断的时间间隔等。所以,只有在需要生成加密性强的随机数据的时候才用它。

Java提供的强随机数发生器是java.security.SecureRandom类,该类也是一个线程安全类,使用synchronize方法保证线程安全,但jdk并没有做出承诺在将来改变SecureRandom的线程安全性。因此,同Random一样,在高并发的多线程环境中可能会有性能问题。

在linux的实现中,可以使用/dev/random/dev/urandom作为随机事件源。由于/dev/random是堵塞的,在读取随机数的时候,当熵池值为空的时候会堵塞影响性能,尤其是系统大并发的生成随机数的时候。

真随机数发生器

在Linux系统中,SecureRandom的实现借助了/dev/random/dev/urandom,可以使用硬件噪音生成随机数;

http://random.org/,从1998年开始提供在线真随机数服务了,它用大气噪音生成真随机数。他也提供了Java工具类,可以拿来使用。地址:https://sourceforge.net/projects/randomjapi/

奥,我好像懂了。真随机数生成要求太高了。所以一般都是用伪随机数。

bd3afde23d37cdd3fd0b2e8a0485d79a.png

嗯嗯,是这样子的。

df4504d3574e7e5477cd82f935d52bf0.png

可是,虽然我理解了,但是我还是希望歌曲的随机可以真随机怎么办呢?

2013bdbed0792e06f31e2ffa29f54a34.png

额。

df4504d3574e7e5477cd82f935d52bf0.png

为了躲避这个看(wu)似(li)合(qu)理(nao)的问题,我拉着她回到车子,找了一首她最喜欢的歌,单曲循环了。

ff69be5ee6411a46dc3c9731f2813668.png

来源:微信公众号漫话编程(mhcoding)

3ff467cb9bd8b0e9d443c84f7d592dfc.png

c3f9c38881ac676331704fb354461ed7.png

564fb8820d932aef1957d64404566187.png

5599f05d2908f307f87201f6c06d38d8.png

8ce60c441b401a54c46f911ca6262a17.png

27df9c90cf5fedb42e2113f3c2556040.png

0beb166316b6648fa5cf4685b23fdf7a.png

已标记关键词 清除标记
表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
相关推荐
<p> <strong><span style="font-size:16px;color:#337FE5;"><b><a target="_blank" href="https://edu.csdn.net/bundled/detail/308"></a><a target="_blank" href="https://edu.csdn.net/bundled/detail/308"><span> </span></a></b></span></strong> </p> <p class="ql-long-39788408" style="font-size:11pt;color:#494949;"> <strong><b><strong><a class="ql-link ql-size-12 ql-author-39788408" href="https://edu.csdn.net/bundled/detail/298" target="_blank">[本课程属于AI完整学习路线套餐,该套餐已“硬核”上线,点击立即学习!]</a></strong> </b></strong> </p> <p class="ql-long-39788408" style="font-size:11pt;color:#494949;"> <br /> </p> <p> <strong><span style="font-size:16px;color:#337FE5;"><img src="https://img-bss.csdnimg.cn/202011090216454206.png" alt="" /><br /> </span></strong> </p> <p> <strong><span style="font-size:16px;color:#337FE5;"><br /> </span></strong> </p> <p> <strong><span style="font-size:16px;color:#337FE5;">【为什么要学习深度学习和计算机视觉?】</span></strong> </p> <p> <span style="font-family:"background-color:#FFFFFF;">AI人工智能现在已经成为人类发展中最火热的领域。而计算机视觉(CV)是AI中最热门,也是落地最多的一个应用方向<span style="font-family:"background-color:#FFFFFF;">(人脸识别,自动驾驶,智能安防,车牌识别,证件识别)</span>。</span><span style="font-family:"background-color:#FFFFFF;">所以基于人工智能的计算视觉行业必然会诞生大量的工作和创业的机会。如何能快速的进入CV领域,同时兼备理论基础和实战能力,就成了大多数学习者关心的事情,而这门课就是因为这个初衷而设计的。<br /> </span> </p> <p style="font-family:"color:#222226;font-size:14px;background-color:#FFFFFF;"> <br /> </p> <p style="font-family:"color:#222226;font-size:14px;background-color:#FFFFFF;"> <span style="font-size:16px;color:#337FE5;"><strong>【讲师介绍】</strong></span> </p> <p style="font-family:"color:#222226;font-size:14px;background-color:#FFFFFF;"> <span style="font-size:16px;color:#337FE5;"><strong>CH<strong><span style="font-family:"color:#222226;font-size:16px;background-color:#FFFFFF;font-weight:700;">ARLIE 老师</span></strong></strong></span> </p> 1、人工智能算法科学家<br /> 2、深圳市海外高层次人才认定(孔雀人才)<br /> 3、美国圣地亚哥国家超算中心博士后<br /> 4、加利福尼亚大学圣地亚哥全奖博士<br /> 5、参与美国自然科学基金(NSF)及加州能源局 (CEC)资助的392MW IVANPAH等智慧电网项目<br /> 6、21篇国际期刊文章(sci收录17篇),总引用接近1000<br /> 7、第一作者发明专利11份<br /> <p> <br /> </p> <p class="ql-long-24357476" style="font-family:"color:#222226;font-size:14px;background-color:#FFFFFF;"> <span style="font-family:"color:#337FE5;"><span><span style="font-size:16px;"><strong>【推荐你学习这门课的理由:</strong></span><span style="color:#E53333;font-size:16px;"><strong>知识体系完整+丰富学习资料】</strong></span></span></span> </p> <p class="ql-long-24357476" style="font-family:"color:#222226;font-size:14px;background-color:#FFFFFF;"> <span class="ql-author-24357476" style="font-family:""></span> </p> <p class="MsoNormal" style="font-family:"color:#222226;font-size:14px;background-color:#FFFFFF;"> 1、本课程总计9大章节,是一门系统入门计算机视觉的课程,未来将持续更新。 </p> <p class="MsoNormal" style="font-family:"color:#222226;font-size:14px;background-color:#FFFFFF;"> <span>2</span>、<span>课程从计算机视觉理论知识出发,理论结合实战,手把手的实战代码实现(霍夫变换与模板匹配,</span><span>AlexNet OCR</span><span>应用</span><span>,VGG</span><span>迁移学习,多标签分类算法工程)</span> </p> <p class="MsoNormal" style="font-family:"color:#222226;font-size:14px;background-color:#FFFFFF;"> <span>3</span>、<span>带你了解最前沿技术,</span><span>各类型算法的优点和缺点,掌握数据增强,</span><span>Batchnormalization, Dropout</span><span>,迁移学习等优化技巧,搭建实用的深度学习应用模型</span> </p> <p class="MsoNormal" style="font-family:"color:#222226;font-size:14px;background-color:#FFFFFF;"> <span>4</span>、学习完后,你将具有深度学习与计算视觉的项目能力,比如大学生学完可以具备独立完成机器视觉类毕业设计的能力,在求职过程中可以体系化的讲解机器视觉核心知识点,初步达到人工智能领域机器视觉工程师的水平 </p> <span style="color:#222226;font-family:PingFangSC-Regular, "font-size:14px;background-color:#FFFFFF;"></span> <p style="font-family:"color:#222226;font-size:14px;background-color:#FFFFFF;"> <br /> </p> <p class="ql-long-24357476" style="font-family:"color:#222226;font-size:14px;background-color:#FFFFFF;"> <strong><span style="color:#337FE5;font-size:16px;">【学完后我将达到什么水平?】</span></strong> </p> <p class="ql-long-24357476"> <span>1、<span style="font-family:"">零基础入门计算视觉,学习掌握并应用从经典图像处理到深度学习分类任务的要点知识</span></span> </p> <p class="ql-long-24357476"> <span>2、<span style="font-family:"">掌握数据增强,迁移学习等优化技巧,搭建实用的深度学习应用模型</span></span> </p> <p class="ql-long-24357476"> <span>3、<span style="font-family:"">学习完课程,可以独立应用多个经典算法和深度学习算法</span></span> </p> <p class="ql-long-24357476"> <span>4、<span style="font-family:"">以</span><span style="font-family:"">大学毕业设计,面试找工作为目标,</span><span style="font-family:"">手把手带大家编程,即使没有太多计算视觉的背景知识也可以循序渐进完成课程,获得实战项目的经验</span></span> </p> <p class="ql-long-24357476"> <br /> </p> <p class="ql-long-24357476"> <span style="color:#337FE5;"><b><span style="background-color:#FFFFFF;color:#337FE5;"><span style="font-size:16px;color:#337FE5;">【面向人群】</span></span></b></span> </p> <p class="ql-long-24357476"> <span>1、对AI感兴趣,想要系统学习计算机视觉的学员</span> </p> <p class="ql-long-24357476"> <span>2、<span style="font-family:"color:#222226;font-size:14px;background-color:#FFFFFF;">需要毕业设计的大学生</span></span> </p> <p class="ql-long-24357476"> <span>3、<span style="font-family:"color:#222226;font-size:14px;background-color:#FFFFFF;">做图像分析或相关数据分析的研究生</span></span> </p> <p class="ql-long-24357476"> <span>4、<span style="font-family:"color:#222226;font-size:14px;background-color:#FFFFFF;">准备面试计算视觉和深度学习岗位的应聘者</span></span> </p> <p class="ql-long-24357476"> <span>5、<span style="font-family:"color:#222226;font-size:14px;background-color:#FFFFFF;">希望在项目中引入计算视觉</span><span style="font-family:"color:#222226;font-size:14px;background-color:#FFFFFF;">/</span><span style="font-family:"color:#222226;font-size:14px;background-color:#FFFFFF;">深度学习技术的开发人员</span></span> </p> <p class="ql-long-24357476"> <br /> </p> <p class="ql-long-24357476"> <b><span style="font-family:"font-size:16px;background-color:#FFFFFF;color:#337FE5;"><span style="font-size:16px;color:#337FE5;">【课程知识体系图</span><span style="font-size:16px;color:#337FE5;">】</span></span></b> </p> <p class="ql-long-24357476"> <span><b><img src="https://img-bss.csdnimg.cn/202007140746422581.png" alt="" /></b></span> </p> <p class="ql-long-24357476"> <span><b><br /> </b></span> </p> <p class="ql-long-24357476"> <span style="font-size:16px;color:#337FE5;"><b>【实战项目】</b></span> </p> <p class="ql-long-24357476"> <b><img src="https://img-bss.csdnimg.cn/202007150352244062.png" alt="" /><img src="https://img-bss.csdnimg.cn/202007150517376530.png" alt="" /></b> </p> <p class="ql-long-24357476"> <br /> </p>
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页