精华内容
下载资源
问答
  • 笔记本cpu和台式cpu有什么区别

    千次阅读 2020-05-07 21:35:32
    笔记本cpu和台式cpu都是电脑处理器,很多用户就会问什么区别呢,其实本质上没有太大的区别,架构基本一致,主要是在功耗的区别,一般来说笔记本由于空间狭小散热问题,功耗比较低,下面来看看详细的区别吧。...

    相关知识超链接放在最前面:(正在写相关文章补充ing,超链接可能还没有)
    笔记本内存条和台式内存条区别:
    https://blog.csdn.net/azj2019/article/details/105982795
    笔记本显卡和台式机显卡区别:
    https://blog.csdn.net/azj2019/article/details/105982308


    笔记本cpu和台式cpu都是电脑处理器,很多用户就会问有什么区别呢,其实本质上没有太大的区别,架构基本一致,主要是在功耗的区别,一般来说笔记本由于空间狭小散热问题,功耗比较低,下面来看看详细的区别吧。


    一、性能上不同
    对于使用者来说,最关心的只是性能问题,用大白话来说同代产品台式电脑cpu比笔记本cpu要强大,原因就有以下方面。(注:以下阐述都是在同代产品的比较,否则没有意义,也不是绝对的,只是普遍区别)

    1、功耗:挑选电脑尤其是游戏本时候,详细页总会写上功耗TDP来吸引买家,功耗是影响性能很大的一个方面(一般来说,同代产品功耗越大性能越好,但这不是绝对的,这样说只是方便小白理解)。笔记本cpu和台式机cpu最大的区别就是功耗的区别。笔记本的空间狭小,散热非常重要。所以一般笔记本的功耗远低于台式机CPU的功耗。(i5 3230M TDP35W i5 3470 TDP 77W。)这也就是为什么往往同代产品下台式机cpu性能更好。

    2、频率:频率怎么理解呢,可以理解为车速吧,频率越高,相当于车速越高,跑的就越快,单位时间内处理信息多,电脑就没有卡顿的感觉(也就是可以认为频率越高越好,发烧玩家喜欢超频就是想办法加电压提高频率)由于功耗的限制,笔记本CPU的默认频率一般都比较低,待机频率则更低了。低压U的默认频率甚至能低到1GHZ左右。所以性能上一般比较低。

    3、针脚:针脚相当于马路车道数量,车道越多是不是以为越不容易交通堵塞?所以如果你是小白,理解为针脚越多越好就行(真实情况不是哈,不过买电脑挑选CPU一般也不会看针脚数,自己组装电脑的也没必要看本文了,除外!)台式电脑cpu和笔记本cpu针脚是不一样的。桌面的CPU(intel为例)一般是LGA1150 1155等。笔记本则是PGA封装的988针脚。

    4、核心与线程:(小白理解为核心越多,线程越多越好就行,但买电脑的时候不要轻易听信多核cpu就是好的哦!总有些坑爹玩意)台式机I5是四核四线程。笔记本的i5则是双核四线程。i7、i3的核心规格则基本一样。
    在这里插入图片描述


    二、指代不同
    笔记本CPU:英文称Mobile CPU(移动CPU),除了追求性能,也追求低热量和低耗电。
    台式电脑CPU:包括运算逻辑部件、寄存器部件和控制部件等,英文Logic components;运算逻辑部件,可以执行定点或浮点算术运算操作、移位操作以及逻辑操作,也可执行地址运算和转换。

    三、特点不同
    笔记本CPU:制造工艺往往比同时代的台式机CPU更加先进,因为Mobile CPU中会集成台式机CPU中不具备的电源管理技术,而且会先采用更高的微米精度。
    台式电脑CPU:要根据指令的功能,产生相应的操作控制信号,发给相应的部件,从而控制这些部件按指令的要求进行动作。

    四、优势不同
    笔记本CPU:采用了多种全新的处理器技术,包括超级传输技术(HyperTransport), 同时内置内存控制器。HyperTransport技术和设计灵活的高速系统总线,既可消除或缓解输入输出的瓶颈,又可提高带宽以及减少延迟时间,能明显提升系统的整体性能。
    台式电脑CPU:解释计算机指令以及处理计算机软件中的数据, 并执行指令。在微型计算机中又称微处理器,计算机的所有操作都受CPU控制,CPU的性能指标直接决定了微机系统的性能指标。

    五、电脑后期升级区别
    随着科技的发展电脑更新换代的加速,特别是一些游戏厂商不断的推陈出新,游戏对电脑硬件配置的要求越来越高。当前的电脑配置跟不上的话,只能进行升级。
    台式机由于空间性能以及存储比较大,后期升级就比较方便,可以说可以升级更换任何一个硬件。
    笔记本的显卡和CPU无法升级,只能增加内存和硬盘。
    总而言之,台式电脑升级空间比笔记本大得多

    六、散热功能区别
    由于笔记本小巧便捷性高,笔记本的内部空间受到限制,在散热性能方面不如台式机的机箱,尤其是高性能的笔记本,性能越高,功耗就越大,
    在玩游戏的时候无疑会带来高发热量,并且散热有局限性。
    所以笔记本出现硬件温度高是在所难免的事情。而台式机自身机箱内部空间较大,加之可以享受更好的散热方案,例如更换更好的CPU散热器、增加水冷散热,增加机箱风扇等。

    七、电脑配置区别
    看似相同或者差不多的电脑配置,台式机的性能要优于笔记本电脑,无论是在处理器还是显卡方面,台式机电脑性能完胜。通过以下一组配置简单的对比就可以很明显看出区别:
    在这里插入图片描述
    八、体积不同
    台式机占地庞大,笔记本便于携带。
    从内部结构上来讲,台式机和笔记本的架构是一样的。只不过由于笔记本受空间限制,很多设备是和主板整合的。
    包括CPU和显卡,都是焊在主板上的(好像也有显卡不焊的了)。因此笔记本电脑无法单独更换CPU和显卡。

    九、电源配置不同
    笔记本电池续航能力限制、空间狭小造成的散热困难等很多原因,笔记本电脑需要分流器才可以连接电源。台式机可以不用加装电源适配器就可以直接连接电源。

    注:以上内容由原文链接修改而成,若涉嫌侵权请联系作者。

    展开全文
  • 需求 我现在有一个很耗cpu的matlab程序,一台电脑多核并行也要好久,然后想到我有两台电脑,能不能两台电脑连接同一个局域网,建成集群,然后两台电脑cpu一起并行运算 参考论文 ...基于Matlab多核并行集群搭建及性能...

    需求

    我现在有一个很耗cpu的matlab程序,一台电脑多核并行也要好久,然后想到我有两台电脑,能不能两台电脑连接同一个局域网,建成集群,然后两台电脑的cpu一起并行运算


    参考论文

    http://www.cqvip.com/QK/80675A/201724/674000873.html
    基于Matlab多核并行集群搭建及性能分析
    《电子技术与软件工程》2017年 第24期 | 顾慧 内蒙古师范大学网络技术学院 内蒙古自治区呼和浩特市010022


    软硬件配置

    matlab: 两台电脑都是matlabR2018a
    系统: win10
    电脑A:i5-9400f的六核cpu
    电脑B:i5-3470的四核cpu

    MATLAB Distributed Computing Server

    步骤

    1. 两台电脑连接到同一局域网下,我是连接到同一个wifi下,然后cmd指令systeminfo,然后看自己现在连接的是哪个网,找到其对应的ip (比如我的是无线)

    在这里插入图片描述

    记住其中的ip地址,如图,我两台电脑的ip分别是 :

    电脑A: 192.168.1.119
    电脑B: 192.168.1.111
    
    2. 进入matlab的toolbox\distcomp\bin目录下运行如下两条指令,安装mdce程序
    !mdce install
    !mdce start
    

    在这里插入图片描述
    选择左边的addMatlabToWindowsFirewall.bat在资源管理器打开,然后用管理员模式运行这个文件,来打开防火墙端口。
    在这里插入图片描述
    在这里插入图片描述
    然后弹出的cmd窗口一闪而过,就运行完了。 (要加入集群的电脑都执行这个操作)

    3. 在放有代码的电脑上以管理员模式运行上图的admincenter.bat ,我的代码放在这电脑A上,就在A电脑执行如下操作:

    在这里插入图片描述
    然后会弹出节点管理界面:
    在这里插入图片描述
    在这里添加两台电脑的ip地址 :
    在这里插入图片描述

    点击ok之后,他会花一些时间去“Adding Hosts and Updating”:


    后续没有了,好久前做的,因为不是很稳定就放弃了。鉴于经常有人问我后续。就补上一个相似的链接

    https://www.it610.com/article/1304031095888580608.htm

    展开全文
  • 前面的不完整回忆中写到了学校的286、386和486,标准的称呼其实应该是80286、80386和80486。...80486是一个很短命的处理器,我印象中大概也就一年左右的时间这个处理器就淘汰了,所以我们学校机房中一共只有那么
      前面的不完整回忆中写到了学校的286、386和486,标准的称呼其实应该是80286、80386和80486。80286是16位的处理器,80386是32位的处理器,不过这么笼统的说386好像也不太准确,但是区分80386SX和80386DX,区别在于SX数据总线为16位而DX是32位。80486是一个很短命的处理器,我印象中大概也就一年左右的时间这个处理器就淘汰了,所以我们学校机房中一共只有那么四五台486机器。印象中这80486好像就是升级版的80386加上一个数字协处理器80387组成的,速度比386快了很多。按道理说下一个版本的处理器应该叫80586,不过美国法律不允许纯数字成为商标,不受保护,所以Intel就为80586换名。当时好像是花了500万美元请了一个公司取的名字,就是大名鼎鼎的Pentium,中文名字也很好听——奔腾。Pentium的起始频率是60MHz,最高大概有200MHz,当时学校机房中的机器清一色的奔腾166,电脑房中也普遍是奔腾166,所以我觉得这个频率应该是当时最畅销的。
      前面说了说奔腾的由来,不过大家不要误会,我不打算写CPU发展史(说到这,发现自己对以前的CPU还真是每一代都知道,一下子想到非常优秀但被Intel为了P4战略而主动放弃的图拉丁,P4的超长流水线设计导致了性能一直比同主频的AMD要差。),这一篇我是要写我自己的电脑硬件,前面这些是一个铺垫。大4,和一个同学不知怎么就说起自己弄一台电脑在宿舍玩,两人一拍即合。当时还给父母写了一封信,说了自己要买一台电脑,当时好像是要了1000块钱。当时家里条件并不怎么好,弟弟也已经上大2了。不过父母还是很支持了我,写到这有眼圈有点红了。新的内容大体上还记得,首先说了自己要买一台电脑,然后说电脑是以后必备的一项技能,讲的最多的是我从小就特别喜欢做小制作,但是由于条件所限并不能自由发挥,而电脑的出现让我可以在电脑世界中自由的创建一切,而不再需要其它的东西。这是我真实的想法,从小我就喜欢做各种东西,除了一把枪是买的玩具外所有的玩具都是我自己做的,玩具做的最多的就是汽车,为了做公共汽车更真实,还专门去公共汽车站趴地上看公交车的减震器、转向系统(在我小学就提出了汽车后轮转向时两个轮子走的距离不一样,是怎么样实现的,后来还特地去问会修车的大姨父,他告诉我有一个差速器,不过原理没给我讲,反正知道了载重汽车后轴上的大鼓包就是差速器)。应该说,我选择学汽车专业做跟我从小就喜欢汽车有关(没能学成计算机上汽车专业我最想知道的就是差速器是怎么设计的,后来学到了,真是巧妙,机械之美!),那时候家里没有什么材料,木头很多,各种工具倒是很多,父亲是瓦匠,两个叔叔一个是木匠一个算是铁匠吧(各种五金工作都干过),所以从小我就会用各种工具,受益一生。不过受材料限制,我很多想法是无法实现的,比如想做遥控的汽车,家里根本不可能拿出钱来去买那些电子设备,所以只能用现有材料去做。好像扯得有点远了,如果讲小时候的业绩恐怕比这个不完整回忆写得还要长。当我遇到电脑后,真的就觉得遇到了一个能够完全让我施展的平台,不再有限制,立刻就爱上了,一直到现在。
      当时我们俩一共有2600块钱,于是在电子市场就转啊,那时候电脑非常贵,正常配置的根本买不起,只能买二手的。转了好几天,从好多家找到配件,最后算是拼出了一台电脑,我自己的第一台电脑(买的时候就跟同学说好了,毕业后我给他补一些钱,然后电脑归我)。我第一台电脑的配置如下:
      CPU:AMD K75,你没看错,是AMD的,可不是K7哦,对应Intel的奔腾75,主频75MHz。
      主板:不知道啦,只知道BIOS是Phoenix做的。
      内存:8MB*4 EDO内存,夸张吧,当年P166好的才配32MB内存,从那时候开始我就喜欢大内存。
      硬盘:好像是富士通的,270MB,你没看错,是270MB。
      键盘:不记得什么牌子了,键盘是新的。
      鼠标:用的是DOS时代的鼠标(学校的286和386机房不提供鼠标)
      音箱:新买的,不记得什么牌子了。
      显示器:一台二手显示器,14吋,刷新率只能到60Hz(可以设置75,但是屏幕会变得很小,并且无法调大,太老了)
      显卡:无。当年没什么显卡概念,都是主板上直接带了VGA的适配器,显卡概念最开始出现应该是Voodoo,称之为3D加速卡。扯远了,不说了。
      基本上就这配置了,当时我们俩买这台电脑主要是玩DOS游戏,不过实际装的还是windows系统。
      由于我的32MB内存是从两个渠道来的,所以不兼容,操作系统装不上,装完重启后会出错。我不断地更改设置,来回折腾内存条的位置,2天重新装了20多遍操作系统,最后终于成功了。这也是我上一篇为什么说windows97在我装完系统后非常稳定,没有出过错,因为安装的过程中出错比较多。不过这台机器还很有意思,只要一段时间不使用就会出现问题,如果装完系统好用后,每天都使用的话就不会出错,但是遇到放假回家,开学再回来就会出现内存不匹配现象。毕业了把电脑搬回家后也是折腾了好久才让其稳定工作。
      这台电脑能干啥呢?你不要惊奇,它可以用VB5编程,可以玩极品飞车2特别版,可以很流畅的玩星际争霸(我得说,暴雪就是牛X),可以很流畅的用NEOGEO模拟器玩拳皇96。
      因为硬盘很小,所以装完win97后都要开始瘦身,那时候不像现在有这么多高手给做现成的瘦身系统,只能自己简单处理一下,大概能将装完127MB的windows缩减到80多MB。我用这台电脑主要用来编程,使用VB5,装完VB5后,还能剩下几十MB的空间。不过这台电脑是我和同学轮流使用的,每个人一天,有时候他需要玩稍大点的游戏,就需要把VB卸载然后装他的游戏。后来我觉得太麻烦,就使用了磁盘压缩,大概能把数据压缩将近一半,当然,如果装星际争霸那就肯定到不了一半了,因为星际争霸本身的数据就已经压缩得非常好了。正常情况下270MB的硬盘最后应该能存下450MB左右的数据。
      这台电脑一直服役到2001年,在2002年送给了我的表弟继续用,不过大概半年左右后人家也新买电脑了,这台电脑扔哪我就不知道了。
    展开全文
  • 设计一个只能创建一个唯一实例的类——单例模式 1. 背景  老师布置了一个思考题:设计一个只能创建一个唯一实例的类。让我们只要想一下思路即可。自己的第一反应就是设计模式中的单例模式。自己百度了一下单例...

    设计一个只能创建一个唯一实例的类——单例模式


    1. 背景


         老师布置了一个思考题:设计一个只能创建一个唯一实例的类。让我们只要想一下思路即可。自己的第一反应就是设计模式中的单例模式。自己百度了一下单例模式,下面附上自己百度到的认为最好的一篇文章。


    2.备注


         转载主要出自:作者刘伟。链接为:http://blog.csdn.net/lovelion。特在此说明


    3.具体内容



    3.1 单例模式的动机

          对于一个软件系统的某些类而言,我们无须创建多个实例。举个大家都熟知的例子——Windows任务管理器,如图3-1所示,我们可以做一个这样的尝试,在Windows的“任务栏”的右键弹出菜单上多次点击“启动任务管理器”,看能否打开多个任务管理器窗口?如果你的桌面出现多个任务管理器,我请你吃饭,微笑(注:电脑中毒或私自修改Windows内核者除外)。通常情况下,无论我们启动任务管理多少次,Windows系统始终只能弹出一个任务管理器窗口,也就是说在一个Windows系统中,任务管理器存在唯一性。为什么要这样设计呢?我们可以从以下两个方面来分析:其一,如果能弹出多个窗口,且这些窗口的内容完全一致,全部是重复对象,这势必会浪费系统资源,任务管理器需要获取系统运行时的诸多信息,这些信息的获取需要消耗一定的系统资源,包括CPU资源及内存资源等,浪费是可耻的,而且根本没有必要显示多个内容完全相同的窗口;其二,如果弹出的多个窗口内容不一致,问题就更加严重了,这意味着在某一瞬间系统资源使用情况和进程、服务等信息存在多个状态,例如任务管理器窗口A显示“CPU使用率”为10%,窗口B显示“CPU使用率”为15%,到底哪个才是真实的呢?这纯属“调戏”用户,给用户带来误解,更不可取。由此可见,确保Windows任务管理器在系统中有且仅有一个非常重要。


                                                                           图3-1 Windows任务管理器


     回到实际开发中,我们也经常遇到类似的情况,为了节约系统资源,有时需要确保系统中某个类只有唯一一个实例,当这个唯一实例创建成功之后,我们无法再创建一个同类型的其他对象,所有的操作都只能基于这个唯一实例。为了确保对象的唯一性,我们可以通过单例模式来实现,这就是单例模式的动机所在。

     

    3.2 单例模式概述

          下面我们来模拟实现Windows任务管理器,假设任务管理器的类名为TaskManager,在TaskManager类中包含了大量的成员方法,例如构造函数TaskManager(),显示进程的方法displayProcesses(),显示服务的方法displayServices()等,该类的示意代码如下:


    class TaskManager
    {
         public TaskManager() {……} //初始化窗口
         public void displayProcesses()  {……} //显示进程
         public void  displayServices() {……} //显示服务
         ……
    }

    为了实现Windows任务管理器的唯一性,我们通过如下三步来对该类进行重构:

          (1)  由于每次使用new关键字来实例化TaskManager类时都将产生一个新对象,为了确保TaskManager实例的唯一性,我们需要禁止类的外部直接使用new来创建对象,因此需要将TaskManager的构造函数的可见性改为private,如下代码所示:


    private TaskManager() {……}

           (2)  将构造函数改为private修饰后该如何创建对象呢?不要着急,虽然类的外部无法再使用new来创建对象,但是在TaskManager的内部还是可以创建的,可见性只对类外有效。因此,我们可以在TaskManager中创建并保存这个唯一实例。为了让外界可以访问这个唯一实例,需要在TaskManager中定义一个静态的TaskManager类型的私有成员变量,如下代码所示:


    private static TaskManager tm = null;

         (3)  为了保证成员变量的封装性,我们将TaskManager类型的tm对象的可见性设置为private,但外界该如何使用该成员变量并何时实例化该成员变量呢?答案是增加一个公有的静态方法,如下代码所示:


    public static TaskManager getInstance()
    {
        if (tm == null)
        {
            tm = new TaskManager();
        }
        return tm;
    }

           在getInstance()方法中首先判断tm对象是否存在,如果不存在(即tm == null),则使用new关键字创建一个新的TaskManager类型的tm对象,再返回新创建的tm对象;否则直接返回已有的tm对象。

          需要注意的是getInstance()方法的修饰符,首先它应该是一个public方法,以便供外界其他对象使用,其次它使用了static关键字,即它是一个静态方法,在类外可以直接通过类名来访问,而无须创建TaskManager对象,事实上在类外也无法创建TaskManager对象,因为构造函数是私有的。 

     

    思考

    为什么要将成员变量tm定义为静态变量?

           通过以上三个步骤,我们完成了一个最简单的单例类的设计,其完整代码如下:


    class TaskManager
    {
         private static TaskManager tm = null;
         private TaskManager() {……} //初始化窗口
         public void  displayProcesses() {……} //显示进程
         public void  displayServices() {……} //显示服务
         public static TaskManager getInstance()
         {
            if (tm == null)
            {
                tm = new TaskManager();
            }
            return tm;
        }
       ……
    }

           在类外我们无法直接创建新的TaskManager对象,但可以通过代码TaskManager.getInstance()来访问实例对象,第一次调用getInstance()方法时将创建唯一实例,再次调用时将返回第一次创建的实例,从而确保实例对象的唯一性。

          上述代码也是单例模式的一种最典型实现方式,有了以上基础,理解单例模式的定义和结构就非常容易了。单例模式定义如下: 

    单例模式(Singleton Pattern):确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。单例模式是一种对象创建型模式。

          单例模式有三个要点:一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。

           单例模式是结构最简单的设计模式一,在它的核心结构中只包含一个被称为单例类的特殊类。单例模式结构如图3-2所示:

          单例模式结构图中只包含一个单例角色:

          ● Singleton(单例):在单例类的内部实现只生成一个实例,同时它提供一个静态的getInstance()工厂方法,让客户可以访问它的唯一实例;为了防止在外部对其实例化,将其构造函数设计为私有;在单例类内部定义了一个Singleton类型的静态对象,作为外部共享的唯一实例。


    3.3 负载均衡器的设计与实现

           Sunny软件公司承接了一个服务器负载均衡(Load Balance)软件的开发工作,该软件运行在一台负载均衡服务器上,可以将并发访问和数据流量分发到服务器集群中的多台设备上进行并发处理,提高系统的整体处理能力,缩短响应时间。由于集群中的服务器需要动态删减,且客户端请求需要统一分发,因此需要确保负载均衡器的唯一性,只能有一个负载均衡器来负责服务器的管理和请求的分发,否则将会带来服务器状态的不一致以及请求分配冲突等问题。如何确保负载均衡器的唯一性是该软件成功的关键。

          Sunny公司开发人员通过分析和权衡,决定使用单例模式来设计该负载均衡器,结构图如图3-3所示:

            在图3-3中,将负载均衡器LoadBalancer设计为单例类,其中包含一个存储服务器信息的集合serverList,每次在serverList中随机选择一台服务器来响应客户端的请求,实现代码如下所示:

    import java.util.*;
    
    //负载均衡器LoadBalancer:单例类,真实环境下该类将非常复杂,包括大量初始化的工作和业务方法,考虑到代码的可读性和易理解性,只列出部分与模式相关的核心代码
    class LoadBalancer {
    	//私有静态成员变量,存储唯一实例
    	private static LoadBalancer instance = null;
    	//服务器集合
    	private List serverList = null;
    	
    	//私有构造函数
    	private LoadBalancer() {
    		serverList = new ArrayList();
    	}
    	
    	//公有静态成员方法,返回唯一实例
    	public static LoadBalancer getLoadBalancer() {
    		if (instance == null) {
    			instance = new LoadBalancer();
    		}
    		return instance;
    	}
    	
    	//增加服务器
    	public void addServer(String server) {
    		serverList.add(server);
    	}
    	
    	//删除服务器
    	public void removeServer(String server) {
    		serverList.remove(server);
    	}
    	
    	//使用Random类随机获取服务器
    	public String getServer() {
    		Random random = new Random();
    		int i = random.nextInt(serverList.size());
    		return (String)serverList.get(i);
    	}
    }


         编写如下客户端测试代码:


    class Client {
    	public static void main(String args[]) {
            //创建四个LoadBalancer对象
    		LoadBalancer balancer1,balancer2,balancer3,balancer4;
    		balancer1 = LoadBalancer.getLoadBalancer();
    		balancer2 = LoadBalancer.getLoadBalancer();
    		balancer3 = LoadBalancer.getLoadBalancer();
    		balancer4 = LoadBalancer.getLoadBalancer();
    		
    		//判断服务器负载均衡器是否相同
    		if (balancer1 == balancer2 && balancer2 == balancer3 && balancer3 == balancer4) {
    			System.out.println("服务器负载均衡器具有唯一性!");
    		}
    		
    		//增加服务器
    		balancer1.addServer("Server 1");
    		balancer1.addServer("Server 2");
    		balancer1.addServer("Server 3");
    		balancer1.addServer("Server 4");
    		
    		//模拟客户端请求的分发
    		for (int i = 0; i < 10; i++) {
                String server = balancer1.getServer();
    			System.out.println("分发请求至服务器: " + server);
          }
    	}
    }


            编译并运行程序,输出结果如下:

    服务器负载均衡器具有唯一性!

    分发请求至服务器:  Server 1

    分发请求至服务器:  Server 3

    分发请求至服务器:  Server 4

    分发请求至服务器:  Server 2

    分发请求至服务器:  Server 3

    分发请求至服务器:  Server 2

    分发请求至服务器:  Server 3

    分发请求至服务器:  Server 4

    分发请求至服务器:  Server 4

    分发请求至服务器:  Server 1

            虽然创建了四个LoadBalancer对象,但是它们实际上是同一个对象,因此,通过使用单例模式可以确保LoadBalancer对象的唯一性。


    3.4 饿汉式单例与懒汉式单例的讨论

          Sunny公司开发人员使用单例模式实现了负载均衡器的设计,但是在实际使用中出现了一个非常严重的问题,当负载均衡器在启动过程中用户再次启动该负载均衡器时,系统无任何异常,但当客户端提交请求时出现请求分发失败,通过仔细分析发现原来系统中还是存在多个负载均衡器对象,导致分发时目标服务器不一致,从而产生冲突。为什么会这样呢?Sunny公司开发人员百思不得其解。

          现在我们对负载均衡器的实现代码进行再次分析,当第一次调用getLoadBalancer()方法创建并启动负载均衡器时,instance对象为null值,因此系统将执行代码instance= new LoadBalancer(),在此过程中,由于要对LoadBalancer进行大量初始化工作,需要一段时间来创建LoadBalancer对象。而在此时,如果再一次调用getLoadBalancer()方法(通常发生在多线程环境中),由于instance尚未创建成功,仍为null值,判断条件(instance== null)为真值,因此代码instance= new LoadBalancer()将再次执行,导致最终创建了多个instance对象,这违背了单例模式的初衷,也导致系统运行发生错误。

          如何解决该问题?我们至少有两种解决方案,在正式介绍这两种解决方案之前,先介绍一下单例类的两种不同实现方式,饿汉式单例类和懒汉式单例类。

     

    1.饿汉式单例类

          饿汉式单例类是实现起来最简单的单例类,饿汉式单例类结构图如图3-4所示:

           从图3-4中可以看出,由于在定义静态变量的时候实例化单例类,因此在类加载的时候就已经创建了单例对象,代码如下所示:

    class EagerSingleton { 
        private static final EagerSingleton instance = new EagerSingleton(); 
        private EagerSingleton() { } 
    
        public static EagerSingleton getInstance() {
            return instance; 
        }   
    }

          当类被加载时,静态变量instance会被初始化,此时类的私有构造函数会被调用,单例类的唯一实例将被创建。如果使用饿汉式单例来实现负载均衡器LoadBalancer类的设计,则不会出现创建多个单例对象的情况,可确保单例对象的唯一性。
     

    2.懒汉式单例类与线程锁定

          除了饿汉式单例,还有一种经典的懒汉式单例,也就是前面的负载均衡器LoadBalancer类的实现方式。懒汉式单例类结构图如图3-5所示:

         从图3-5中可以看出,懒汉式单例在第一次调用getInstance()方法时实例化,在类加载时并不自行实例化,这种技术又称为延迟加载(Lazy Load)技术,即需要的时候再加载实例,为了避免多个线程同时调用getInstance()方法,我们可以使用关键字synchronized,代码如下所示:
    [java] view plaincopy
    1. class LazySingleton {   
    2.     private static LazySingleton instance = null;   
    3.   
    4.     private LazySingleton() { }   
    5.   
    6.     synchronized public static LazySingleton getInstance() {   
    7.         if (instance == null) {  
    8.             instance = new LazySingleton();   
    9.         }  
    10.         return instance;   
    11.     }  
    12. }  


          该懒汉式单例类在getInstance()方法前面增加了关键字synchronized进行线程锁,以处理多个线程同时访问的问题。但是,上述代码虽然解决了线程安全问题,但是每次调用getInstance()时都需要进行线程锁定判断,在多线程高并发访问环境中,将会导致系统性能大大降低。如何既解决线程安全问题又不影响系统性能呢?我们继续对懒汉式单例进行改进。事实上,我们无须对整个getInstance()方法进行锁定,只需对其中的代码“instance = new LazySingleton();”进行锁定即可。因此getInstance()方法可以进行如下改进:
    [java] view plaincopy
    1. public static LazySingleton getInstance() {   
    2.     if (instance == null) {  
    3.         synchronized (LazySingleton.class) {  
    4.             instance = new LazySingleton();   
    5.         }  
    6.     }  
    7.     return instance;   
    8. }  
           问题貌似得以解决,事实并非如此。如果使用以上代码来实现单例,还是会存在单例对象不唯一。原因如下:

          假如在某一瞬间线程A和线程B都在调用getInstance()方法,此时instance对象为null值,均能通过instance == null的判断。由于实现了synchronized加锁机制,线程A进入synchronized锁定的代码中执行实例创建代码,线程B处于排队等待状态,必须等待线程A执行完毕后才可以进入synchronized锁定代码。但当A执行完毕时,线程B并不知道实例已经创建,将继续创建新的实例,导致产生多个单例对象,违背单例模式的设计思想,因此需要进行进一步改进,在synchronized中再进行一次(instance == null)判断,这种方式称为双重检查锁定(Double-Check Locking)。使用双重检查锁定实现的懒汉式单例类完整代码如下所示:

    [java] view plaincopy
    1. class LazySingleton {   
    2.     private volatile static LazySingleton instance = null;   
    3.   
    4.     private LazySingleton() { }   
    5.   
    6.     public static LazySingleton getInstance() {   
    7.         //第一重判断  
    8.         if (instance == null) {  
    9.             //锁定代码块  
    10.             synchronized (LazySingleton.class) {  
    11.                 //第二重判断  
    12.                 if (instance == null) {  
    13.                     instance = new LazySingleton(); //创建单例实例  
    14.                 }  
    15.             }  
    16.         }  
    17.         return instance;   
    18.     }  
    19. }  

           需要注意的是,如果使用双重检查锁定来实现懒汉式单例类,需要在静态成员变量instance之前增加修饰符volatile,被volatile修饰的成员变量可以确保多个线程都能够正确处理,且该代码只能在JDK 1.5及以上版本中才能正确执行。由于volatile关键字会屏蔽Java虚拟机所做的一些代码优化,可能会导致系统运行效率降低,因此即使使用双重检查锁定来实现单例模式也不是一种完美的实现方式。 

     

    扩展

    IBM公司高级软件工程师Peter    Haggar 2004年在IBM developerWorks上发表了一篇名为《双重检查锁定及单例模式——全面理解这一失效的编程习语》的文章,对JDK    1.5之前的双重检查锁定及单例模式进行了全面分析和阐述,参考链接:http://www.ibm.com/developerworks/cn/java/j-dcl.html

     

    3.饿汉式单例类与懒汉式单例类比较

          饿汉式单例类在类被加载时就将自己实例化,它的优点在于无须考虑多线程访问问题,可以确保实例的唯一性;从调用速度和反应时间角度来讲,由于单例对象一开始就得以创建,因此要优于懒汉式单例。但是无论系统在运行时是否需要使用该单例对象,由于在类加载时该对象就需要创建,因此从资源利用效率角度来讲,饿汉式单例不及懒汉式单例,而且在系统加载时由于需要创建饿汉式单例对象,加载时间可能会比较长。

          懒汉式单例类在第一次使用时创建,无须一直占用系统资源,实现了延迟加载,但是必须处理好多个线程同时访问的问题,特别是当单例类作为资源控制器,在实例化时必然涉及资源初始化,而资源初始化很有可能耗费大量时间,这意味着出现多线程同时首次引用此类的机率变得较大,需要通过双重检查锁定等机制进行控制,这将导致系统性能受到一定影响。


    3.5 一种更好的单例实现方法

           饿汉式单例类不能实现延迟加载,不管将来用不用始终占据内存;懒汉式单例类线程安全控制烦琐,而且性能受影响。可见,无论是饿汉式单例还是懒汉式单例都存在这样那样的问题,有没有一种方法,能够将两种单例的缺点都克服,而将两者的优点合二为一呢?答案是:Yes!下面我们来学习这种更好的被称之为Initializationon Demand Holder (IoDH)的技术。

          在IoDH中,我们在单例类中增加一个静态(static)内部类,在该内部类中创建单例对象,再将该单例对象通过getInstance()方法返回给外部使用,实现代码如下所示:

    [java] view plaincopy
    1. //Initialization on Demand Holder  
    2. class Singleton {  
    3.     private Singleton() {  
    4.     }  
    5.       
    6.     private static class HolderClass {  
    7.             private final static Singleton instance = new Singleton();  
    8.     }  
    9.       
    10.     public static Singleton getInstance() {  
    11.         return HolderClass.instance;  
    12.     }  
    13.       
    14.     public static void main(String args[]) {  
    15.         Singleton s1, s2;   
    16.             s1 = Singleton.getInstance();  
    17.         s2 = Singleton.getInstance();  
    18.         System.out.println(s1==s2);  
    19.     }  
    20. }  

           编译并运行上述代码,运行结果为:true,即创建的单例对象s1s2为同一对象。由于静态单例对象没有作为Singleton的成员变量直接实例化,因此类加载时不会实例化Singleton,第一次调用getInstance()时将加载内部类HolderClass,在该内部类中定义了一个static类型的变量instance,此时会首先初始化这个成员变量,由Java虚拟机来保证其线程安全性,确保该成员变量只能初始化一次。由于getInstance()方法没有任何线程锁定,因此其性能不会造成任何影响。

          通过使用IoDH,我们既可以实现延迟加载,又可以保证线程安全,不影响系统性能,不失为一种最好的Java语言单例模式实现方式(其缺点是与编程语言本身的特性相关,很多面向对象语言不支持IoDH)。

     

    练习

    分别使用饿汉式单例、带双重检查锁定机制的懒汉式单例以及IoDH技术实现负载均衡器LoadBalancer

          至此,三种单例类的实现方式我们均已学习完毕,它们分别是饿汉式单例、懒汉式单例以及IoDH


    3.6 单例模式总结

           单例模式作为一种目标明确、结构简单、理解容易的设计模式,在软件开发中使用频率相当高,在很多应用软件和框架中都得以广泛应用。

     

    1.主要优点

           单例模式的主要优点如下:

           (1) 单例模式提供了对唯一实例的受控访问。因为单例类封装了它的唯一实例,所以它可以严格控制客户怎样以及何时访问它。

           (2) 由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象单例模式无疑可以提高系统的性能。

           (3) 允许可变数目的实例。基于单例模式我们可以进行扩展,使用与单例控制相似的方法来获得指定个数的对象实例,既节省系统资源,又解决了单例单例对象共享过多有损性能的问题。

     

    2.主要缺点

           单例模式的主要缺点如下:

           (1) 由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。

           (2) 单例类的职责过重,在一定程度上违背了“单一职责原则”。因为单例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色,包含一些业务方法,将产品的创建和产品的本身的功能融合到一起。

           (3) 现在很多面向对象语言(JavaC#)的运行环境都提供了自动垃圾回收的技术,因此,如果实例化的共享对象长时间不被利用,系统会认为它是垃圾,会自动销毁并回收资源,下次利用时又将重新实例化,这将导致共享的单例对象状态的丢失。

     

    3.适用场景

           在以下情况下可以考虑使用单例模式:

           (1) 系统只需要一个实例对象,如系统要求提供一个唯一的序列号生成器或资源管理器,或者需要考虑资源消耗太大而只允许创建一个对象。

           (2) 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。

     

    思考

    如何对单例模式进行改造,使得系统中某个类的对象可以存在有限多个,例如两例或三例?【注:改造之后的类可称之为多例类。】



    展开全文
  • 时候会发现一个很奇怪的现象,无论配置几个CPU,但是在win7的系统里面,只能看到2个CPU: 配置了4CPU,在处理器里看也是4个,但是只能使用2个:   原因 1、Windows 7最多只支持两个CPU socket,每个...
  • 栗子 晓查 发自 凹非寺量子位 报道 | 公众号 QbitAI一块小小的CPU多少个晶体管?几十亿个。单枪匹马造出一个CPU乃至完整的电脑需要多长时间?位大牛在《...
  • 程序员的成长之路互联网/程序员/成长/职场关注阅读本文大概需要 5.4 分钟。对于开发来讲,使用 Mac 电脑的好处,下面简单列举几:首先,macOS 很安全和稳定,...
  • CPU个数、CPU核心数、CPU线程数

    千次阅读 2018-09-28 11:46:53
     我们在选购电脑的时候,CPU一个需要考虑到核心因素,因为它决定了电脑的性能等级。CPU从早期的单核,发展到现在的双核,多核。CPU除了核心数之外,还有线程数之说,下面文本就来解释一下CPU的核心数与线程数的...
  • 电脑cpu怎么看 怎么看cpu好坏 (全文)

    千次阅读 2016-12-30 22:19:11
    前些天为大家介绍了如何看电脑配置,其中也简单的提到了,怎么看电脑cpu,以及判断...查看cpu的方法很多,也非常的简单,最直接的方法是进入-- 我的电脑 -在空白区域右键单击鼠标 选择-- 属性 即可看到电脑
  • 转载:http://blog.csdn.net/sunvince/article/details/6533016 这是CU上的一个问题...   from: ...在SMP上,想把所有的用户 态进程运行在一个CPU上,腾出其它CPU干其它事。Linux能通过
  • CPU是如何设计出来的? 设计CPU到底难在哪里? 导读 这几天,刷遍朋友圈的新闻就是:中兴被“剑封喉”,被美国停止一切芯片进口和系统软件服务。这对于芯片依赖美国的中兴来说,基本上...
  • cpu有哪些架构

    千次阅读 2015-11-12 14:18:41
    author:skate time:2009/12/17 ...这几天在下载RPM包的时候,总会看见x86,x86-64,IA64,i386,i586等,这些都是cpu的架构,有点记不清了,所以特此记录下,以备日后查询 CPU架构 Architect
  • 第一章CPU的典型故障剖析  常见的CPU故障大致以下几种:散热... 故障现象:某用户一台AthlonCPU电脑,平日使用一直正常,一天突然无法开机,屏幕无显示信号输出,开始认定显卡出现故障。用替换法检查后,发
  • 最近在闲鱼上攒了一台深度学习用的电脑。全部二手,一共花了10400。 CPU,9700k。 9700我估计应该也没问题。 板子 z390p。 这板子给i7的cpu超频的话,估计不太行。可以内存小超。华硕的板子,质量应该不差。 ...
  •  我们在选购电脑的时候,CPU一个需要考虑到核心因素,因为它决定了电脑的性能等级。CPU从早期的单核,发展到现在的双核,多核。CPU除了核心数之外,还有线程数之说,下面文本就来解释一下CPU的核心数与线程数的...
  • CPU的核与逻辑CPU

    千次阅读 2015-07-09 21:59:10
    CPU一台计算机的重要组成部件。它相当于一个人的“大脑”。其中文名称是:中央处理器;英文名称是:Central Processing Unit,简写为CPU,它是一台计算机的核心部件。  CPU一般由逻辑运算单元、控制单元和存储...
  • 如何选择一台适合Java开发的电脑

    千次阅读 2020-08-20 07:50:00
    前言最近在群里老同学求推荐适合Java开发用的电脑,所以胖哥就用我知道的电脑知识来帮助大家选择适合开发的电脑配置。因为我自己家里的主机已经带不动两 IDEA 了,更别提开 Dock...
  • CPU架构:CPU架构详细介绍

    万次阅读 多人点赞 2020-04-25 10:12:43
    目前市场上的CPU分类主要分两大阵营,一个是intel、AMD为首的复杂指令集CPU,另一个是以IBM、ARM为首的精简指令集CPU。不同品牌的CPU,其产品的架构也不相同,Intel、AMD的CPU是X86架构,IBM公司的CPU是PowerPC...
  • CPU卡芯片通俗地讲就是指芯片内含有一个微处理器,它的功能相当于一台微型计算机。人们经常使用的集成电路卡(IC卡)上的金属片就是CPU卡芯片。CPU卡可适用于金融、保险、交警、政府行业等多个领域,具有 用户空间 ...
  • CPU卡发卡总结(

    千次阅读 2012-05-15 18:03:37
    概述:CPU卡包含一个微处理器,其功能相当于一台微型计算机CPU卡内集成电路中包括中央处理器(CPU)、只读存储器(ROM)、随机存储器(RAM)、电可擦除可编程只读存储器(EEPROM)等。  使用FMCOS,由传输管理、...
  • 开机cpu100%

    千次阅读 2009-05-25 08:38:00
    cpu运行负荷总是100%,其中个system进程一直占用了90%以上的cpu,导致system idle process永远是0 聊城信 我把system进程关掉,蹦出一个窗体提示还有60秒关机。cmd---------------shutdown -a然后重启。没事,...
  • 通俗地说,就是能最多用到多少内存的一个问题。数据在存储器(RAM)中存放是规律的 ,CPU在运算的时候需要把数据提取出来就需要知道数据在那里 ,这时候就需要挨家挨户的找,这就叫做寻址,但如果地址太多超出了CPU...
  • 前面我们这里假设的 CPU 很基础,所有指令都是 8 位,操作码只占了前面 4 位,即便用尽 4 位,也只能代表 16 指令,而且我们几条指令,是用后 4 位来指定内存地址,因为 4 位最多只能表示 16 值,所以我们只能...
  • CPU 进程 线程

    千次阅读 2018-03-20 17:30:06
    CPU是中央处理器,是一台计算机的运算核心和控制核心。 2:进程 进程,一个进程就是一个具有独立功能的应用程序,关于某个数据集合上的一次 运行活动。进程是系统进行资源分配和调度的一个独立单位。 3:线程 ...
  • 1.说明 CPU(Central Processing ...一个物理CPU可以1个或者多个物理内核, 一个物理内核可以作为1个或者2个逻辑CPU。 2.物理CPU 物理CPU就是计算机上实际安装的CPU, 物理CPU数就是主板上实际插入的CPU数量。 在L...
  • 近来闲着无事,突然想把家里的两台主机省出来一台,俩人玩一台主机,那电费得省多少啊,于是乎就开始找各种软件进行测试,最后选定了ASTER使用。 下面是本人的主机配置,以及需要的东西。 首先需要的是你的显卡...
  • 这两从一定程度上都可以反映一台机器的繁忙程度。 CPU 使用率反映的是当前 CPU 的繁忙程度,忽高忽低的原因在于占用 CPU 处理时间的进程可能处于 IO 等待状态但却还未释放进入wait。 平均负载(load average)是...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 98,849
精华内容 39,539
关键字:

一台计算机只能有一个cpu