精华内容
下载资源
问答
  • 交互设计的十大可用性原则

    千次阅读 2020-06-10 14:42:59
    交互设计领域有丰富的理论沉淀,最著名和经典的理论当属人机交互大师雅各布·尼尔森(Jakob Nielsen)博士在1995提出的尼尔森十大可用性原则(Jakob Nielsen’s Ten Usability Heuristics),该理论是针对PC端交互...

    产品经理有必要投入精力来学习和练习交互设计。
    交互设计领域有丰富的理论沉淀,最著名和经典的理论当属人机交互大师雅各布·尼尔森(Jakob Nielsen)博士在1995提出的尼尔森十大可用性原则(Jakob Nielsen’s Ten Usability Heuristics),该理论是针对PC端交互设计提出的,但同时也适用于移动端交互设计。我们将结合具体案例详细阐述这十条指导原则,产品经理在绘制线框图时要注意遵循这些原则。

    1,反馈原则(Visibility of system status)
    系统应该在合理的时间、用正确的方式,向用户提示或反馈目前系统在做什么、发生了什么。
    人机交互的基本原则是,让系统和用户之间保持良好的沟通和信息传递。系统要告知用户发生了什么,预期是什么,如果系统不能及时向用户反馈合适的信息,用户必然会感到失控和焦虑,不知道下一步要做什么。
    以下是遵循反馈原则的一些常见设计案例。
    ● 安装程序时显示进度条,并预估还需要多久结束。
    ● 上传文件时显示进度条,并提示预估剩余时间。
    ● 提交表单时,如果校验失败,则在填写有误的内容旁边提示错误原因。
    ● 程序未响应时,系统会让用户选择是关闭程序还是等待程序响应。

    2,隐喻原则(Match between system and the real world)
    系统要采用用户熟悉的语句、短语、符号来表达意思。遵循真实世界的认知、习惯,让信息的呈现更加自然,易于辨识和接受。
    在人机交互设计中,程序的沟通和表达、功能的呈现,都要用最自然的、用户容易理解的方式,避免采用计算机程序语言的表达方式。设计时要采用符合真实世界认知的方式,让用户通过联想、类比等方法轻松地理解程序想表达的含义。
    例如,音乐播放器App,功能按钮设计,即便不做说明,用户也很容易理解每个按钮是做什么用的。

    3,回退原则(User control and freedom)
    用户经常会不小心操作错误,需要有一个简单的功能,让程序迅速恢复到错误发生之前的状态。
    用户误操作的概率极高。对于误操作,软件系统应该尽量提供“撤销”“重做”或“反悔”的功能,让系统迅速返回错误发生之前的状态。当然,不是所有操作都是可以“反悔”的,比如,你可以撤销一笔错误的订单,但不能撤销一笔成功的转账交易。

    以下是遵循回退原则的常见设计案例。
    编辑类软件都提供撤销功能,例如Word、美图秀秀等。
    ● 点击删除或关闭按钮后,会让用户进行二次确认。
    ● 电商平台允许在一定的规则下取消订单。

    4,一致原则(Consistency and standards)
    同样的情景、环境下,用户进行相同的操作,结果应该一致;系统或平台的风格、体验也应该保持一致。
    软件设计、产品设计中有很多约定俗成的规范,虽然没有明文规定,但大家都在遵守,因为用户已经习惯了这些规范。我们在进行设计时,应该遵循惯例,并且保持系统的一致感,不要盲目地标新立异。
    例如,在App底部的导航图标中,“首页”永远排在第一个,个人中心(“我的”)永远排在最后。并且对于类似“首页”“购物车”“订单”等常见按钮,不同App的设计样式都非常相似。如果你特立独行地把个人中心放在第一个位置,或者采用奇怪的图标作为个人中心的icon,用户使用时肯定会觉得别扭。

    此外,在一个或多个系统中,要采用统一的设计风格。不论是图标的选用,还是布局的规划,要保持整齐的一致性,这样用户容易理解,并且容易习惯和适应。
    例如,Office软件中包含的各个产品,其界面布局和设计风格就保持了高度一致。

    5,防错原则(Error prevention)
    系统要避免错误发生,这好过出错后再给提示。
    进行设计时,首先要考虑如何避免错误发生,其次再考虑如何检查、校验异常。这样做一方面可以让问题更简单,另一方面可以让用户避免或减少无谓操作。
    例如,有些时候,为了防止用户重复提交或重复点击,第一次点击按钮后就将按钮置灰,直到处理完成才恢复。
    有时还会通过调整按钮顺序,避免用户误点。比如,对于很重要的操作,为了防止用户顺手误点,会将二次确认对话框中的“是”和“否”两个按钮对调位置。因为常见的对话框都将“是”按钮放在第一个位置,所以用户在操作时,很容易产生条件反射,顺手点击第一个按钮,然后才突然发现自己点错了。虽然看起来有些别扭,但是很有效,因为多点一次要好过误删文件。这种设计在软件卸载、App取消会员订阅等操作中也非常常见,只不过后两种情况下主要是为了做一些心理暗示和引导,避免用户卸载或退订。

    6,记忆原则(Recognition rather than recall)
    让系统的相关信息在需要的时候显示出来,减轻用户的记忆负担。
    计算机应该减轻人们的记忆负担,而不是相反。例如,当切换页面时,不应该让用户记住不同页面的内容,而应该在合适的地方积极地呈现或提示之前的信息。
    例如,几乎所有的App和PC端的搜索引擎都会记录用户的搜索历史并呈现给用户

    再例如,在所有的电商购物流程中,在用户提交订单后,都会出现一个核对页面,让用户再次核对填写是否正确。这个设计非常有用,我就经常在下单时忘了修改默认地址,再次核对时才发现。

    7,灵活易用原则(Flexibility and efficiency of use)
    系统的用户中,中级用户往往最多,初级和高级用户相对较少。系统应为大多数人设计,同时兼顾少数人的需求,做到灵活易用。
    灵活易用原则不仅是一个交互设计原则,也代表了一种软件产品设计理念:系统既要做得简单、易用,让所有中级用户用起来得心应手;也要提供必要的帮助,让刚入门的初级用户顺利上手;还需要支持灵活的个性化定制,让高级用户能够以进阶的方式使用系统,充分发挥其价值。
    让高级用户灵活定制的最典型的例子是各类软件和App的配置功能,基本上所有软件都会提供定制化功能,从快捷键设置,到页面布局,再到自定义参数,软件系统会尽量提供全面的个性化设置功能,来满足不同用户的使用诉求和习惯。

    例如Word的自定义功能,提供了非常强大的配置能力,用户可以对Word的UI实现颠覆性的重新设置。

    8,简约设计原则(Aesthetic and minimalist design)
    对话中不应该包含无关的或没必要的信息;增加或强化一些信息就意味着弱化另一些信息。
    重点太多,相当于没有重点。在视觉设计中,要掌握好“突出标记”的度,以及内容的呈现方式。

    9,容错原则(Help users recognize, diagnose, and recover from errors)
    错误信息应该用通俗易懂的语言说明,而不是只向用户提示错误代码;提示错误信息时要给出解决建议。
    对于很多运行时错误或异常,计算机程序都会返回某个错误代码,但是对于用户来讲,看到这些错误代码并不明白发生了什么,所以一定要将错误代码转换成用户能看懂的语句,并告诉用户解决的建议。
    访问网站时,如果页面不存在,服务器提供的标准错误提示是404错误,很多用户并不理解404是什么意思。最好将页面就对此做处理,将错误提示转换成用户能理解的表述,而且给出解决建议。

    再例如,做得比较好的表单填写页面,对于不符合格式要求的内容会立即进行提示,而不是等到用户提交时才去校验并提示错误;提示时除了指出填写错误,还会说明规范的填写要求,以便用户理解错误原因并做出修正。

    10,帮助原则(Help and documentation)
    对于一个设计良好的系统,用户往往不需要经过培训就能轻松上手使用,但是提供帮助文档依然是很有必要的。帮助信息应该易于检索,通过明确的步骤引导用户解决问题,并且不能太复杂。
    现在的软件产品,尤其是C端产品普遍做了良好的交互设计,可以帮助用户快速学习使用,而不用阅读、理解复杂的说明文档。
    然而,B端产品的复杂性比C端产品高很多,因为B端产品蕴含很多业务流程的规则,系统中的一个按钮可能代表了一个复杂的业务处理规则,如果不了解整个业务场景和处理规则,是很难理解按钮的操作含义的。
    因此,对于B端产品,用户进行自助服务、自助操作的难度高很多,B端产品的帮助文档依然有存在的必要。产品设计人员要尽量在前端交互上做好引导提示,对于复杂的规则和逻辑,可以考虑通过帮助文档来指导用户。

    展开全文
  • 数据库设计的重要和设计原则

    千次阅读 2017-02-22 11:47:42
    数据库设计的重要和设计原则

    说起数据库设计,相信大家都明白怎么回事,但说起数据库设计的重要性,我想大家也只是停留在概念上而已,到底如何重要?怎么重要呢?今天就将我至今为止的理解向大家阐述下。

    一个不良的数据库设计,必然会造成很多问题,轻则增减字段,重则系统无法运行。我先来说说数据库设计不合理的表现吧:

    1. 与需求不符

    因为这个原因造成的改动量往往是最大。如果进入编码阶段的话,很可能会直接让你崩溃掉。

    2. 性能低下

    含有大数据量的表之间的关联过多;没有合理的字段设计来用于查询而造成的SQL查询语句很复杂;对于大数据量的表没有采用有效的手段去处理;滥用视图等。

    3. 数据完整性丧失

    含有主外键关系的表之间关联字段的设计方式不合理,造成更新与删除操作后程序容易出错或不完善;使用了已经删除或丢失掉的数据。

    4. 可扩展性性太差

    表设计的与业务绑定的太紧密、单一,造成表的可拓展性、可修改性太差,无法新需求的要求。

    5. 非必要数据冗余量太大

    没用的垃圾数据存储过多,不仅占用资源,还影响查询效率。

    6. 不利于计算或统计

    缺少必要的联系性或统计性字段或用于计算统计的字段分散于多个表中,造成计算统计的步骤繁琐,甚至无法计算统计。

    7. 没有详尽的数据记录信息

    缺少必要的字段,造成无法跟踪数据变化、用户操作,也无法进行数据分析。

    8. 表之间的耦合性太大

    多张表之间关联的过于紧密,造成一张表发生变化而影响到其他表。

    9. 字段设计考虑不周

    字段长度过短或字段类型过于明确,造成可发挥、可拓展的空间太小。

    大多数的程序员对于软件开发的出发点认识不是很明确,总是认为实现功能才是重要的,在简单了解完基本需求后就急忙进入编码阶段,对于数据库设计思考的比较少、比较简单,大多设计都只停留在表面上,这往往是要命的,会为系统留下很多隐患。要么是写代码开发过程中才发现问题,要么就是系统上线运转后没多久就出现问题,还有可能给后期维护增加了很多工作量。如果到了那个时候再想修改数据库设计或进行优化等同于推翻重来。

    数据库是整个软件应用的根基,是软件设计的起点,它起着决定性的质变作用,因此我们必须对数据库设计高度重视起来,培养设计良好数据库的习惯,是一个优秀的软件设计师所必须具备的基本素质条件!

    那么我们要做到什么程度才是对的呢?下面就说说数据库设计的原则

    1.  数据库设计最起码要占用整个项目开发的40%以上的时间

    数据库是需求的直观反应和表现,因此设计时必须要切实符合用户的需求,要多次与用户沟通交流来细化需求,将需求中的要求和每一次的变化都要一一体现在数据库的设计当中。如果需求不明确,就要分析不确定的因素,设计表时就要事先预留出可变通的字段,正所谓“有备无患”。

    2.  数据库设计不仅仅停留于页面demo的表面

    页面内容所需要的字段,在数据库设计中只是一部分,还有系统运转、模块交互、中转数据、表之间的联系等等所需要的字段,因此数据库设计绝对不是简单的基本数据存储,还有逻辑数据存储。

    3.  数据库设计完成后,项目80%的设计开发在你脑海中就已经完成了

    每个字段的设计都是有他必要的意义的,你在设计每一个字段的同时,就应该已经想清楚程序中如何去运用这些字段,多张表的联系在程序中是如何体现的。换句话说,你完成数据库设计后,程序中所有的实现思路和实现方式在你的脑海中就已经考虑过了。如果达不到这种程度,那当进入编码阶段后,才发现要运用的技术或实现的方式数据库无法支持,这时再改动数据库就会很麻烦,会造成一系列不可预测的问题。

    4.  数据库设计时就要考虑到效率和优化问题

    一开始就要分析哪些表会存储较多的数据量,对于数据量较大的表的设计往往是粗粒度的,也会冗余一些必要的字段,已达到尽量用最少的表、最弱的表关系去存储海量的数据。并且在设计表时,一般都会对主键建立聚集索引,含有大数据量的表更是要建立索引以提供查询性能。对于含有计算、数据交互、统计这类需求时,还要考虑是否有必要采用存储过程。

    5.  添加必要的(冗余)字段

    像“创建时间”、“修改时间”、“备注”、“操作用户IP”和一些用于其他需求(如统计)的字段等,在每张表中必须都要有,不是说只有系统中用到的数据才会存到数据库中,一些冗余字段是为了便于日后维护、分析、拓展而添加的,这点是非常重要的,比如黑客攻击,篡改了数据,我们便就可以根据修改时间和操作用户IP来查找定位。

    6.  设计合理的表关联

    若多张表之间的关系复杂,建议采用第三张映射表来关联维护两张表之间的关系,以降低表之间的直接耦合度。若多张表涉及到大数据量的问题,表结构尽量简单,关联也要尽可能避免。

    7.  设计表时不加主外键等约束性关联,系统编码阶段完成后再添加约束性关联

    这样做的目的是有利于团队并行开发,减少编码时所遇到的问题,表之间的关系靠程序来控制。编码完成后再加关联并进行测试。不过也有一些公司的做法是干脆就不加表关联。

    8.  选择合适的主键生成策略

    主键生成策略大致可分:int自增长类型(identity、sequence)、手动增长类型(建立单独一张表来维护)、手动维护类型(如userId)、字符串类型(uuid、guid)。int型的优点是使用简单、效率高,但多表之间数据合并时就很容易出现问题,手动增长类型和字符串类型能很好解决多表数据合并的问题,但同样也都有缺点:前者的缺点是增加了一次数据库访问来获取主键,并且又多维护一张主键表,增加了复杂度;而后者是非常占用存储空间,且表关联查询的效率低下,索引的效率也不高,跟int类型正好相反。

    终上所述,我们可见数据库设计在整个软件开发的起到的举足轻重的作用,尤其是我说的设计原则的第一点,数据库与需求是相辅相成的,我经常把软件开发比作汽车制造。汽车制造会经过图纸设计,模型制作,样车制造,小批量试生产,最后是批量生产等步骤。整个过程环环相扣,后一过程是建立在前一过程正确的前提基础之上的。如果在图纸设计阶段发现了一个纰漏,我们可以重新进行图纸设计,如果到了样车制造阶段发现这个错误,那么我们就要把从图纸设计到样车制造的阶段重来,越到后面发现设计上的问题,所付出的代价越大,修改的难度也越大。

    数据库设计难度其实要比单纯的技术实现的难很多,他充分体现了一个人的全局设计能力和掌控能力,所以在今后的项目中大家一定要着重培养这方面的能力,这里我将我的经验分享给了大家,希望能对大家有所帮助。

    展开全文
  • 尼尔森的十大可用性原则是产品设计与用户体验设计的重要参考标准,值得深入研究与运用。一、状态可见原则用户在网页上的任何操作,不论是单击、滚动还是按下键盘,页面应即时给出反馈。“即时”是指,页面响应时间...

    尼尔森的十大可用性原则是产品设计与用户体验设计的重要参考标准,值得深入研究与运用。

    一、状态可见原则

    用户在网页上的任何操作,不论是单击、滚动还是按下键盘,页面应即时给出反馈。“即时”是指,页面响应时间小于用户能忍受的等待时间。
    例如下拉刷新提示

    二、环境贴切原则

    网页的一切表现和表述,应该尽可能贴近用户所在的环境(年龄、学历、文化、时代背景),而不要使用第二世界的语言。《iPhone人机交互指南》里提到的隐喻与拟物化是很好的实践。此外,还应该使用易懂和约定俗成的表达。
    产品/信息的逻辑符合真实的世界中的一些惯例和人类自然思考逻辑,就是要借助符合自然界和人们常规的逻辑,把他们用到你的产品上,不论是界面上的隐喻、模拟情景等设计都是让产品符合真实的世界,让产品便于用户理解使用。

    三、撤销重做原则

    为了避免用户的误用和误击,网页应提供撤销和重做功能。

    四、一致性原则

    同一用语、功能、操作保持一致。产品在遵循平台惯例的基础上也要保证产品功能操作、控件样式、界面布局、提示信息的一致性,不要让用户在使用产品的时候发现不符合产品规范的地方。

    五、防错原则

    通过网页的设计、重组或特别安排,防止用户出错。用选择替代输入

    六、易取原则

    好记性不如烂笔头。尽可能减少用户回忆负担,把需要记忆的内容摆上台面。

    七、灵活高效原则

    中级用户的数量远高于初级和高级用户数。为大多数用户设计,不要低估,也不可轻视,保持灵活高效。 就是指用户在使用产品时能够方便快捷的完成相关任务或动作,即让用户以最快最便捷的方式完成任务,例如:QQ中我最近使用的表情

    八、易扫原则

    互联网用户浏览网页的动作不是读,不是看,而是扫。易扫,意味着突出重点,弱化和剔除无关信息。让你的相关信息尽量一目了然不要过于复杂繁琐,即让自己的架构简单界面简洁突出重要内容去掉或弱化干扰和不相关的信息/内容。例雅虎中的天气显示…时时场景中突出的就只有天气度数,

    九、容错原则

    帮助用户从错误中恢复,将损失降到最低。如果无法自动挽回,则提供详尽的说明文字和指导方向,而非代码,比如404。就是在用户出错时如何为出错的用户提供及时正确的帮助呢?即要帮助用户识别出错误,分析出错误的原因再帮助用户回到正确的道路上。如果真的不能帮助用户从错误中恢复,也要尽量为用户提供帮助让用户损失降到最低。

    十、人性化帮助原则

    帮助性提示最好的方式是:1、无需提示;2、一次性提示;3、常驻提示;4;帮助文档。

    展开全文
  • Java内存模型相关原则详解

    千次阅读 2019-11-06 12:11:45
    本篇文章就带大家了解一下相关概念、原则等内容。 原子 原子即一个操作或一系列是不可中断的。即使是在多个线程的情况下,操作一旦开始,就不会被其他线程干扰。 比如,对于一个静态变量int x两条线程同时对其.....

    在《Java内存模型(JMM)详解》一文中我们已经讲到了Java内存模型的基本结构以及相关操作和规则。而Java内存模型又是围绕着在并发过程中如何处理原子性、可见性以及有序性这三个特征来构建的。本篇文章就带大家了解一下相关概念、原则等内容。

    原子性

    原子性即一个操作或一系列是不可中断的。即使是在多个线程的情况下,操作一旦开始,就不会被其他线程干扰。

    比如,对于一个静态变量int x两条线程同时对其赋值,线程A赋值为1,而线程B赋值为2,不管线程如何运行,最终x的值要么是1,要么是2,线程A和线程B间的操作是没有干扰的,这就是原子性操作,不可被中断的。

    Java内存模型对以下操作保证其原子性:read,load,assign,use,store,write。我们可以大致认为基本数据类型的访问读写是具备原子性的(前面也提到了long和double类型的“半个变量”情况,不过几乎不会发生)。

    从Java内存模型底层来看有上面的原子性操作,但针对用户来说,也就是我们编写Java的程序,如果需要更大范围的原子性保障,就需要同步关键字——synchronized来保障了。也就是说synchronized中的操作也具有原子性。

    可见性

    可见性是指当一个线程修改了共享变量的值,其他线程能够立即得知这个修改。

    Java内存模型是通过变量修改后将新值同步回主内存,在变量读取前从主内存刷新变量值,将主内存作为传递媒介。可回顾一下上篇文章的图。

    JMM

    无论普通变量还是volatile变量都是如此,只不过volatile变量保证新值能够立马同步到主内存,使用时也立即从主内存刷新,保证了多线程操作时变量的可见性。而普通变量不能够保证。

    除了volatile,synchronized和final也能够实现可见性。

    synchronized实现的可见性是通过“对一个变量执行unlock操作之前,必须先把此变量同步回主内存中”来保证的。

    主要有两个原则:线程解锁前,必须把共享变量的最新值刷新到主内存中;线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新读取最新的值。

    final的可见性是指:被final修饰的字段在构造器中一旦初始化完成,并且构造器没有把“this”的引用传递出去,那在其他线程中就能看见final的值。

    有序性

    在Java内存模型中有序性可归纳为这样一句话:如果在本线程内观察,所有操作都是有序的,如果在一个线程中观察另一个线程,所有操作都是无序的。

    有序性是指对于单线程的执行代码,执行是按顺序依次进行的。但在多线程环境中,则可能出现乱序现象,因为在编译过程会出现“指令重排”,重排后的指令与原指令的顺序未必一致。

    因此,上面归纳的前半句指的是线程内保证串行语义执行,后半句则指指“令重排现”象和“工作内存与主内存同步延迟”现象。

    同样,Java语言提供了volatile和synchronized两个关键字来保证线程之间操作的有序性。

    指令重排

    计算机执行指令经过编译之后形成指令序列。一般情况,指令序列是会输出确定的结果,且每一次的执行都有确定的结果。

    CPU和编译器为了提升程序执行的效率,会按照一定的规则允许进行指令优化。但代码逻辑之间是存在一定的先后顺序,并发执行时按照不同的执行逻辑会得到不同的结果。

    • 编译器优化重排序:编译器在不改变单线程程序语义的前提下,重新安排语句执行顺序。
    • 指令级并行重排序:处理器采用了指令级并行技术来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应及其的执行顺序。
    • 内存系统的重排序:处理器使用缓存和读/写缓冲区,使得加载和存储操作看上去可能是乱序执行。

    举个例来说明一下多线程中可能出现的重排现象:

    class ReOrderDemo {
        int a = 0;
        boolean flag = false;
     
        public void write() {
            a = 1;                   //1
            flag = true;             //2
        }
         
        public void read() {
            if (flag) {                //3
                int i =  a * a;        //4
                ……
            }
        }
    }
    

    在上面的代码中,单线程执行时,read方法能够获得flag的值进行判断,获得预期结果。但在多线程的情况下就可能出现不同的结果。

    比如,当线程A进行write操作时,由于指令重排,write方法中的代码执行顺序可能会变成下面这样:

    flag = true;             //2
    a = 1;                   //1
    

    也就是说可能会先对flag赋值,然后再对a赋值。这在单线程中并不影响最终输出的结果。

    但如果与此同时,B线程在调用read方法,那么就有可能出现flag为true但a还是0,这时进入第4步操作的结果就为0,而不是预期的1了。

    请记住,指令重排只会保证单线程中串行语义执行的一致性,不会关心多线程间语义的一致性。这也是为什么在写单例模式时需要考虑添加volatile关键词来修饰,就是为了防止指令重排导致的问题。

    JMM提供的解决方案

    在了解了原子性、可见性以及有序性问题后,看看JMM是提供了什么机制来保证这些特性的。

    原子性问题,除了JVM自身提供的对基本数据类型读写操作的原子性外,对于方法级别或者代码块级别的原子性操作,可以使用synchronized关键字或者重入锁(ReentrantLock)保证程序执行的原子性。

    而工作内存与主内存同步延迟现象导致的可见性问题,可以使用synchronized关键字或者volatile关键字解决。它们都可以使一个线程修改后的变量立即对其他线程可见。

    对于指令重排导致的可见性问题和有序性问题,则可以利用volatile关键字解决。volatile的另一个作用就是禁止重排序优化。

    除了靠sychronized和volatile关键字之外,JMM内部还定义一套happens-before(先行发生)原则来保证多线程环境下两个操作间的原子性、可见性以及有序性。

    先行发生原则

    如果仅靠sychronized和volatile关键字来保证原子性、可见性以及有序性,那么编写并发程序会十分麻烦。为此在Java内存模型中,还提供了happens-before原则来辅助保证程序执行的原子性、可见性以及有序性的问题。该原则是判断数据是否存在竞争、线程是否安全的依据。

    happens-before规则:

    • 程序次序规则:在一个线程内,程序前面的操作先于后面的操作。
    • 监视器锁规则:一个unlock操作先于后面对同一个锁的lock操作发生。
    • volatile变量规则:对一个volatile变量的写操作先行发生于后面对这个变量的读操作,也就是说读取的值肯定是最新的。
    • 线程启动规则:Thread对象的start()方法调用先行发生于此线程的每一个动作。
    • 线程加入规则:Thread对象的结束先行发生于join()方法返回。
    • 线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生,可以通过interrupted()方法检测到是否有中断发生。
    • 对象终结规则:一个对象的初始化完成(构造函数执行结束)先行发生于它的finalize()方法的开始。
    • 传递性:如果操作A先行发生于操作B,操作B先行发生于操作C,那么操作A先行发生于操作C。

    还拿上面的具体代码来进行说明:

    class ReOrderDemo {
        int a = 0;
        boolean flag = false;
     
        public void write() {
            a = 1;                   //1
            flag = true;             //2
        }
         
        public void read() {
            if (flag) {                //3
                int i =  a * a;        //4
                ……
            }
        }
    }
    

    线程A调用write()方法,线程B调用read()方法,线程A先(时间上的先后)于线程B启动,那么线程B读取到a的值是多少呢?

    现在依据8条原则来进行对照。

    两个方法分别由线程A和线程B调用,不在同一个线程中,因此程序次序原则不适用。

    没有write()方法和read()方法都没有使用同步手段,监视器锁规则不适用。

    没有使用volatile关键字,volatile变量原则不适用。

    与线程启动、终止、中断、对象终结规则、传递性都没有关系,不适用。

    因此,线程A和线程B的启动时间虽然有先后,但线程B执行结果却是不确定,也是说上述代码没有适合8条原则中的任意一条,所以线程B读取的值自然也是不确定的,换句话说就是线程不安全的。

    修复这个问题的方式很简单,要么给write()方法和read()方法添加同步手段,如synchronized。或者给变量flag添加volatile关键字,确保线程A修改的值对线程B总是可见。

    小结

    在这篇文章中介绍了Java内存模型中一些原则,及其衍生出来保证这些原则的方式和方法。也是为我们下面学习volatile这个面试官最爱问的关键字的做好铺垫。欢迎关注微信公众号“程序新视界”继续学习。

    原文链接:《Java内存模型相关原则详解

    《面试官》系列文章:


    程序新视界

    关注程序员的职场生涯,大量优质学习资源、技术文章分享

    程序新视界-微信公众号

    展开全文
  • 降低软件复杂的一般原则和方法

    千次阅读 2019-09-24 10:37:31
    一、前言 斯坦福教授、Tcl语言发明者John Ousterhout 的著作《A Philosophy of Software Design》[1],自出版以来,好评...而冠名为“哲学",则是一些通用的原则和方法论,这些原则方法论串起来,能够形成一个体系。...
  • 尼尔森的十大可用性原则虽然对网页的设计没有直接的视觉影响,但却是网页交互效果的重要引导和参考的依据,很值得每个网页设计师深入学习和研究。 尼尔森是谁?   尼尔森(Jakob Nielsen)是一位人机交互学...
  • 六大设计原则之开闭原则

    万次阅读 多人点赞 2016-08-28 10:32:38
    开闭原则的定义开闭原则是java世界里最基础的设计原则,它指导我们如何建立一个稳定,灵活的系统。开闭原则定义如下:Software entities like classes,modules and functions should be open for extension but ...
  • SMART原则 及 在探索测试中的实践

    千次阅读 2012-11-24 20:18:36
    SMART原则: Specific(具体的):测试需要一个具体的目标。 Measurable(可度量的):有明确的度量可以评估目标是否达成。 Achievable(可实现的):当前的目标应该是可实现的。这潜在地要求将一个大的目标分解为多...
  • 软件维护主要针对一下几种(数据来源未知2333):纠错25%适应21%完善50%预防4%“变化”在软件生命周期中是不可避免的!那么如何在最初的设计中充分考虑到未来的变化,避免因为频繁的变化导致软件复杂度增加...
  • [一般性原则] 一、网站设计原则 第一原则:内容丰富、明确 网站主要是为浏览着提供信息服务的,作为大型企业信息门户网站,必须首先提供种类繁多内容丰富的资讯,使不同的访问者都能够访问到自己想要的信息。...
  • [一般性原则] 一、网站设计原则 第一原则:内容丰富、明确 网站主要是为浏览着提供信息服务的,作为大型企业信息门户网站,必须首先提供种类繁多内容丰富的资讯,使不同的访问者都能够访问到自己想要的信息。...
  • 有的拿完整性说话,必须保留所有的关联性。   观点1:我倾向于去掉所有的关联,为了开发的方便。然后写代码的时候自己留意完整性的问题。 观点2: 如果不采用外键关联的话,很多字段势必得集中在一个表里
  • 高扩展高可用网站的51条原则

    千次阅读 2013-04-24 12:07:38
    高扩展高可用网站的50条原则 A.化简方程 一.不要过度设计 目的:防止设计中出现复杂的解决方案。 适用情形:适用于任何项目,所有大型的或复杂的系统和项目都应该采用该原则。 应用方式:让同行来检查解决方案...
  • 设计原则

    千次阅读 2019-11-07 13:51:50
    本文章只是介绍与讲解各种设计原则的基本概念,以便以后复习使用。具体的原则在代码中的使用我打算在以后整理各种设计模式的时候,再讲讲。
  • 【MySQL】可扩展基本原则

    千次阅读 2018-06-24 20:44:24
    扩展(Scalability):指一个数据库系统通过相应的升级之后所带来处理能力提升的难易程度 横向扩展(Scale Out):通过增加处理节点的方式来提高整体处理能力,简单来说就是通过增加机器来增加整体的处理能力 ...
  • 软件的易用测试原则和方法

    千次阅读 2011-09-16 10:37:39
    易用 考察评定软件的易学易用,各个功能是否易于完成,软件界面是否...对于易用测试可遵循以下原则: 1、完成相同或相近功能的按钮用Frame.框起来,常用按钮要支持快捷方式。 2、完成同一功能或任务的元素放在
  • 端到端原则与命运共享原则

    千次阅读 2018-05-13 11:13:16
    端到端原则(The End-To-End Arguments)起初就是为了解决在通信系统中的在什么地方增加功能最合适,然而在接下来的时间里,它被用来维护公开、增强可靠健壮、保护用户的选择权和使用户的开发更容易等。...
  • 模块独立   模块化设计是指将软件分解为多个独立模块,不同的模块具有不同的功能和职责。每个模块可以独立的进行开发、测试,最后组装成完整的软件。   模块独立是指软件系统中每个模块只涉及软件要求的子功能...
  • 六大设计原则之单一职责原则

    千次阅读 2016-08-17 20:20:28
    单一职责原则单一职责原则(Single Responsibility Principle)–SRP:There should never be more than one reason for a class to change.应该有且仅有一个原因引起类的变更。单一职责原则好处 降低类的复杂每个类...
  • CAP, BASE, 最终一致和五分钟原则

    万次阅读 2017-02-16 16:30:34
    CAP,BASE和最终一致是NoSQL数据库存在的三大基石。而五分钟法则是内存数据存储的理论依据。这个是一切的源头。 CAP     C: Consistency 一致A: Availability 可用(指的是快速获取数据)...
  • SMART原则

    千次阅读 2014-06-04 22:10:54
     S(Specific)——明确  所谓明确就是要用具体的语言清楚地说明要达成的行为标准。明确的目标几乎是所有成功团队的一致特点。很多团队不成功的重要原因之一就因为目标定的模棱两可,或没有将目标有效的传达给...
  • 什么是最少知识原则? 最少知识原则(LKP)说的是一个软件实体应当尽可能少地与其他实体发生相互作用。这里的软件实体是一个广义的概念,不仅包括对象,还包括系统、类、模块、函数、变量等。本节我们主要针对对象来...
  • 为了最大程度去掉影响安全的不可控因素,就需要有一些原则来制约人、制约人的非理性因素。 基本原则一:确保每个保护对象都需要有一个owner 在日常生活中,我们每个人都作为个体存在,对私有资源和公众资源负有...
  • 每个职责都是变化的一个轴线,如果一个方法承担了过多的职责,那么在需求的变迁过程中,需要改写这个方法的可能就越大。 此时,这个方法通常是一个不稳定的方法,修改代码总是一件危险的事情,特别是当两个职责...
  • 编程原则

    千次阅读 2017-02-22 10:52:03
    良好的编程原则与良好的设计工程原则密切相关。本文总结的这些设计原则,帮助开发者更有效率的编写代码,并帮助成为一名优秀的程序员。1.避免重复原则(DRY – Don’t repeat yourself)编程的最基本原则是避免重复...
  • 面向对象设计原则之6-合成复用原则

    万次阅读 2018-07-16 10:04:31
    合成复用原则(Composite Reuse Principle or CRP) 尽量使用对象组合,而不是继承来达到复用的目的。 CRP:Favor polymorphic composition of objects over inheritance as a reuse mechanism. 合成复用原则是...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 465,811
精华内容 186,324
关键字:

关联性原则