知识点_知识点总结 - CSDN
精华内容
参与话题
  • HTML5 全套知识点打包 很值得下载学习

    千次下载 热门讨论 2020-07-30 23:32:33
    HTML5 全套知识点打包 很值得下载学习 包含:揭秘HTML5和CSS3.rar 22个HTML5 技巧一.doc 22个HTML5 技巧二.doc 22个HTML5 技巧三.doc 全方位了解HTML5 .doc HTML5设计原理+.doc HTML5高级程序设计(1).pdf 等等
  • 知识点汇总11

    2019-10-16 16:41:31
    1.BPR是业务流程的重组,有时候会导致组织不稳定,会涉及多方利益。 2.基于业务流程充足的信息系统规划主要步骤:1.系统战略规划阶段,2.系统流程规划阶段,3.系统数据规划阶段,4.系统功能规划阶段,5....

    1.BPR是业务流程的重组,有时候会导致组织不稳定,会涉及多方利益。
    2.基于业务流程充足的信息系统规划主要步骤:1.系统战略规划阶段,2.系统流程规划阶段,3.系统数据规划阶段,4.系统功能规划阶段,5.系统实施阶段
    3.业务重组步骤:启动,拟变革计划,建团队,分析目标流程,重设目标流程,实施新设计,改进,重新开始。读两遍就行
    4.保证BPR启动时就建立有效的领导机制,全员参与,无法衡量的部分,尽量不触及
    5.价值链的组成部分:内部后勤,仓库和存储,成产,市场,销售,客服等
    6.信息系统和增值过程是紧密相连的,是过程本身的一部分
    7.BPM:业务流程管理系统
    8.BPR业务流程重组引起:企业文化转变,业物流程转变,组织管理变化。
    9.价值活动分为:基本活动(内勤外勤售后服务,经营,营销等),和辅助活动(采购,开发,人资记住设施管理等)
    10.ABC法:将“不增值的作业”改进为“可增值的作业”
    11.评估方法要关注:业务流程遵从性评估,业务流程有效性评估,业务流程绩效评估
    12.BPR实施三个层次:观念重建层次,流程重建层级,组织重建层次
    13.BPR:使用的人来执行流程操作,不是输入的人,将地理上分散的资源看作是集中地来处理。决策点下放到基层活动中,并建立对流程的控制。机构设计要围绕企业产出,而不是一项项的做。
    14.业务流程管理分为:成产层,运作层,计划层,战略层。
    15.业务流程分为三类:管理流程,操作流程,支持流程。
    16.业务流程管理BPM:最重要的环节是流程设计
    17.业务流程重组BPR的原则:以流程为中心,团队管理,以客户为导向
    18.r价值系数,f贡献,c成本,瓶颈是增值性分析、
    19.适应阶段:审核提交结果,文档。适当做出改进
    构想阶段:确认范围和工作方式
    推测阶段:指定发布计划,理成本,和产品
    探索阶段:探索功能,减少不确定性
    20.问题分析图:详细设计工具,支持结构化程序设计工具,从左主干上执行,自上而下。
    21.一系列相关项目,子项目,项目集活动称为项目集管理
    22.题干只说分解为各个项目(没说关联,利益的):是项目组合管理
    23.项目集,就是具有协调收益支付的管理特点
    24.项目集论证是从组织战略的角度论证和可行性研究。
    25.按时间顺序项目集发展,为项目集路线图
    26.项目集知识管理包括:跨项目集知识收集和共享,个人和专家知识的挖掘和整理,存储知识和构件集的信息系统建设
    27.项目集生命周期:定义阶段,收益交付阶段,收尾阶段
    28.项目集的决策机构为:项目集指导委员会
    29.项目集关键活动:建立项目集治理结构,组件初始项目集组织,制定项目集管理计划。
    30.项目集指导委员会主要职责:保证愿景和目标一致,项目集批准和启动
    31.项目集组合管理借鉴金融投行的组合理论
    32.项目组合管理是:合并项目,不是组合二项目
    33.项目组合管理的基本过程:项目选择和优先级排序
    34.项目组合管理关心如何选择项目,项目组合中的项目可能没有依赖关系。
    35.项目组合管理实现精化组织战略目标,依赖于交付收益能力
    36.项目管理办公室PMO,资源平衡是重要的职责之一
    37.大型项目不一定要建立组织机构管理
    38.资源平衡是统一综合平衡
    39.项目组合管理,所有项目都要经过:收益风险分析,平衡资源方法论
    40.项目组合管理的两个重要因素:风险评估,提高资源利用率
    41.项目组合管理中心,选择和优先级用到的技术:决策报表技术,财务分析技术,DIPP技术
    42.项目组合管理选择的主要依据平衡收益和风险。决定优先级的决定因素组织战略。
    43.项目排序是:对项目创造的期望价值投入进行分析。
    44.资源往往不够用。
    45.DIPP(资源利用率)=EWM/ETC,DIPP越大越好
    46.项目组合管理是战略级管理:高层决策,自上而下
    47.过程计划体系包括:制定过程,执行过程,监督过程、
    48.大型项目,活动计划之前,必须必考虑项目的过程计划
    49.组织机构项目管理:战略目标
    50.大型活动中:范围和质量容易失真。
    51.制定具体的项目计划,由项目团队做
    52.项目计划首先要关注:活动计划
    53.大型项目,首先关注过程计划。
    54.大型项目在过程中:监督过程最重要。
    55.大型项目过程体系:制定过程,执行过程,监督过程
    56.对项目集中管理:项目管理办公室
    57.项目组合实施过程:评估过程的当前状态,定义愿景和计划,实施过程,改进过程。
    58.项目组合管理/协调对象是:组合管理人员
    59.决定客户机和FTP之间采用SSL协议
    60.客户机和服务器之间交互密码发生在:密码交换阶段。
    61.3DES:两倍于DES的秘钥长度
    62.内外网计算机不能直接通信。
    63.Kerberos是对称秘钥管理系统,PKI是公开的非对称秘钥。
    64.TGT请求话务票据。
    65.IDEA秘钥长度:128位
    66.非对称加密算法有:RSA,ECC
    67.PPTP安全传输,访问公司网络。用于虚拟专用网。
    68.计算机安全五个安全等级:1.自主保护级(自己),2.系统审计保护(商业),3.安全标记保护(政府,银行,能源水电,交通),4.结构化保护(中央),5.访问验证保护级(国防)。自主-审计-标记-结构-访问
    69.公开密钥:加密秘钥是公开的。
    70.S-MIS安全体系,不涉及:应用系统安全
    71.维护信息系统安全:首先要对脆弱性进行评估鉴定
    72.只有数字证书才具有不可抵赖性特征。
    73.安全风险分类:从风险性质分,从风险结果分,从风险源(风险角度)分
    74.基于角色的访问控制:权限分配由应用系统管理员分配
    75.IDS入侵检测技术,大多是被动
    76.信息安全策略设计实施步骤:1.制定安全需求(确认范围,评估风险),2.制定安全目标,3.制定安全规划,4.制定日常维护计划。
    77.VPN:虚拟专用网络,对为网络数据进行加密,在公网上传输私有数据
    78.SSH:可替代telnet,对所有数据进行加密,防止远程管理信息泄露。
    79.SSL:在传输层(TCP/IP层上,应用层下),internet和www服务之间安全传输
    80.2005年12月发布ISO20000标准,10月发布ISO270000标准;2007年7月发布IEEE802.16为3G标准
    81.TLS协议位于传输层
    82.信息系统安全管理体系是:组织在整体or特定范围建立安全方针和目标,及所用的方法体系。
    83.S-MIS安全体系是最安全的信息系统
    84.安全分为:物理安全(设备,环境,电磁辐射,介质完全),技术安全,安全管理
    85.安全审计不包括:可信网站内部信息不泄露
    86.防范网络攻击是提高,确保系统可用性,数据签名确保完整性
    87.防火墙吧对外提供网络服务的设施放置于:DMZ(非军事化区)
    88.硬件和软件通用的是:MIS+S和S-MIS;S2-MIS是硬软件都专用
    89.信息安全,社会层面反映在:网络空间安全的舆论文化,社会行为和技术环境。
    90.数字证书不包括秘钥
    91.加密是M→C,即M=C,解密是C→M即C=M
    92.信息安全流程:评估-响应-防护-评估。
    93.一个单位的安全措施不能照搬别人的
    94.对特定功能执行:管理和执行分离、
    95.通过CA安全认证后的数字证书,可获得主题的公钥。
    96.有选择的记录网络操作信息,保证记录不被篡改,为:基于网络旁路监控的审计。
    97.脆弱性是客观存在的,与威胁和使用制度没有关系。
    98.自主访问控制DAC:指明那些主体对哪些客体可以进行什么操作,如 管理员 指定 数据访问控制。
    99.数据安全目的是实现数据的:机密性,安全性,不可否认性
    知识点汇总1
    知识点汇总2
    知识点汇总3
    知识点汇总4
    知识点汇总5
    知识点汇总6
    知识点汇总7
    知识点汇总8
    知识点汇总9
    知识点汇总10
    知识点汇总11
    知识点汇总12
    知识点汇总13
    知识点汇总14

    展开全文
  • 32个知识点

    2020-05-18 12:01:47
    一、面试岗位选择 1.公司&团队: 第一维度为业务/团队 小公司 大公司 核心业务/团队 〇 ✔ 边缘业务/团队 ✖ 〇 2.岗位匹配度: 与自己发展方向越匹配越好 ... 第二,注重平衡心态,过于紧张...

    一、面试岗位选择

    1.公司&团队:
    第一维度为业务/团队

    小公司 大公司
    核心业务/团队
    边缘业务/团队

    2.岗位匹配度:
    与自己发展方向越匹配越好

    面试准备

    面试准备决定面试成功与否

    影响面试成败三大基石:能力,面试,沟通

            第一,优秀的技术基本功是必要条件,没有技术能力其他的无从谈起。
            第二,注重平衡心态,过于紧张会导致平时会的内容都答不上来。
            第三,与面试官顺畅的沟通,开行的交流,能给你的面试加分,反之可能影响整个面试。
    

    面试准备主要包括:
    一、能力

    	1. 了解应试公司及其岗位
    	2. 系统化复习基础知识
    	3. 对原公司负责的项目进行梳理总结
    	4. 学习典型框架案例
    	5. 阅读常考考点源码
    	6. 针对性准备加分项
    

    二、心态

    尽量收集应试公司岗位所属团队、平均福利等资料信息,知己知彼有助于增加信心。
    面对压力面试时,可进行自我暗示。如:
    这个面试官我可能永远不会遇到。
    失败了也并不可怕。
    

    三、沟通

    1. 提前准备一个简短有特色的自我介绍,包括兴趣特长、技术优势
    2. 避免冷场,回答不上来的问题可主动坦白,并提供应对或处理办法,亦或是询问面试官能否换一个问题。
    3. 当没有听清或不理解问题时,不应强行作答,应与面试官沟通再次确认问题。
    4. 面试细节。包括面部微表情、坐姿、手势,说话语速不要过快或过慢,表达逻辑清晰观点明确,不可随意打断面试官以及谦虚有礼的态度等。
    ps.及时观察面试官的反映。面试官奋笔疾书可能是你给与的信息有用,反之,长时间未有反应,应反思是否跑题。面试官表情不耐烦或深呼吸,可能意味着未能领会考察意图,可以再次询问。
    

    面试考察点

    面试考察点相对综合,一般分为两大块:
    硬技能:
    指基础知识、项目经验、架构能力、应用能力等
    软实力:
    指逻辑思维、沟通协作、管理推进、学习思考、培养潜力等、

    硬技能ç³"谱图

    二、操作系统与网络知识

      • 知识点汇总
      • 知识点详解
        • HTTP
        • TCP
        • 三次握手
        • 四次挥手

    知识点汇总

    操作系统对于服务问题的排查定位很重要,在面试时,一般以了解和应用考察为主,面试题目占的比重不会过高.

    操作系统

    线程共享同一进程资源

    进程间的通信IPC,中间件研发相关职位。6钟原理和使用场景。eg:进程间共享可以使用共享内存,进程间交换可以使用Unix socket或消息队列。

    协程更轻量化,是在用户态进行,调度切换的代价比线程上下文切换要低很多。

    服务之间通过不同的网络协议进行交互,在面试中被考的几率非常大.

    网络知识

    知识点详解


    HTTP

    1. 需要知道协议中的Method,Header,Cookies.
    2. 知道常见状态码含义404:未找到503:服务不可用302:临时移动
    3. 了解HTTPs的交互流程
    4. QUIC基于UDP实现原HTTP功能,现已被标准化为HTTP3协议,类似tcp的流量控制、可靠性保证
    

    TCP

    1. TCP和HTTP在服务交互中使用最多.了解报文标志状态和链接状态有利于抓包分析.
    2. Nagel和ACK 延迟算法是为了解决小包问题和数据载荷比.对于延迟比较敏感且发送频率比较低,可以关闭nagel
    3. KeepALive是在长时间没有数据发送的情况下保持连接可用的机制.需要了解开启和设置方式.
    4. 了解如何通过滑动窗口机制实现流量控制.
    
    • 位于OSI模型的第四层-传输层

    • 面向连接

      • 每次发送数据先要建立连接
    • 双工通信

      • 连接建立后可进行双向通信
    • 可靠

      • 通过对数据包编号,并按序号接受,可确保数据的完整性和有序性
    • 流量控制

      • 通过滑动窗口控制数据的发送速率.滑动窗口的本质是动态缓冲区,接收端根据自己的处理能力,在tcp的Header中动态调整大小,通过ACK应答包通知发送端,进而调整发送速度
    • 拥塞控制

      • 主要通过慢启动,拥塞避免,拥塞发生,快速恢复算法实现
    • 基于字节流

      将数据按字节大小进行编号,接收端通过AKC确认收到的数据编号,保证接收数据的有序性完整性

    除了以上特点,还可以了解tcp协议的报文状态,滑动窗口的工作流程,KeepAlive的参数设置,Nagel算法的细节

    三次握手

    三次握手

    tcp是基于链接的所以在传输数据前需要先建立链接(三次握手是为了建立双向的链接)
    ​ 首先建立链接前需要server端先监听端口,因此初始状态就是listen状态。client端准备建立链接,发送SYN同步包,之后client端的链接状态就变成了SYN_SEND状态.server端收到SYN后同意建立链接,会向client端回复一个ACK.由于tcp是双工传输server端也会同时向client端发送一个同步请求SYN.client端收到后变为established状态,同时client端向server端发送ACK响应回复,收到后server端的链接状态也就变成了established的状态。此时建联完成双方随时可以进行数据传输。

    回答建连的问题时,可以提到syn洪水攻击.即请求端只发送SYN包,而不对接收端的SYNACK包进行回复,使得接收端大量连接处于半连接状态,影响其他正常请求的建连.
    解决方法:设置linux的tcp参数
    tcp_synack_retries=0,加快对于半连接的回收速度,或加大tcp_max_syn_backlog应对少量的syn洪水攻击

    四次挥手

    	四次挥手

    ​ 关闭通信双方都可以先发起,首先链接状态都是established状态。然后可client端先发起了关闭链接请求,向server发送了一个FIN包表示client端已经没有数据要发送。然后client端就进入了FIN_WAIT_1状态。server端收到FIN后返回ACK然后进入close_wait状态。此时server属于半关闭状态,因为此时client不会向server发送数据,server有可能向client端发送数据。当server端数据发送完毕,向client端发送FIN,进入LAST_ACK状态,等待应答就可以关闭链接了。client端收到server端的FIN后,回复ACK然后进入time_wait状态(等待两倍的msl,即最大报文段生存时间来保证链接的可靠关闭)之后才会进入close状态。而server端收到ACK后直接就可以进入close状态。

            为什么需要4次:两端并不是同时都不需要发送数据了
            处于CLOSE_WAIT状态时,HOSTB仍有可能向HOSTA发送数据,HOSTB发送完数据后,才会向HOSTA发送FIN包
            发送关闭连接请求,表示没有数据需要发送,进入wait1,进入last_ACK等待应答,之后就可以closed,
    

    为何HOSTA要在2MSL(Maximum Segment Lifetime 最大报文生存时长)后才关闭连接?

    1. 要保证TCP的全双工连接能可靠关闭
    2. 要保证这次连接中重复的数据段从网络中消失,防止端口重用时可能的数据混淆

    回答问题是也可以提到,有可能大量socket会处于TIME_WAIT和CLOSE_WAIT的问题.
    解决TIME_WAIT过多,可通过开启Linux的tcp参数tw_reuse或tw_recycle能加快TIME_WAIT状态的回收.
    CLOSE_WAIT过多则可能是被动关闭的一方存在代码BUG,没有正确关闭连接导致的

    三、设计模式与Java语言特性

    • 知识点汇总
    • 知识点详解
      • 常用设计模式
        • 单例模式
        • 工厂模式
        • 代理模式
        • 责任链模式
        • 适配器模式
        • 观察者模式
        • 构造者模式
      • Java语言特性
      • Java基础常考点–Map
        • HashMap
        • ConcurrentHashMap
      • Java版本特性
        • 1.8
        • 1.9-1.10
        • 1.11
    • 面试考察点
    • 加分项
    • 真题汇总

    知识点汇总

    该内容需掌握主要两点

    1. 常用设计模式的实现
    2. 各设计模式的使用场景

    设计模式
    Java语言特性

    常见集合类和Java并发工具包(JUC)是常见考点

    知识点详解


    常用设计模式

    有**单例模式,工厂模式,代理模式,观察者模式,**构造者模式,责任链模式,适配器模式等.

    在回答设计模式问题时,可结合实际业务场景,体现对设计模式的理解和应用能力.

    单例模式

    线程安全实现的常见三种方法:

    	1. 静态初始化(饿汉).不管是否使用都会创建
    	2. 双检锁(懒汉).单例变量必须要用volatile修饰.
    	3. 单例注册表.spring中bean的单例模式就是用该方法实现.
    

    工厂模式

    在实际业务中经常用到,也是面试的主要考察点.是创建不同类型实例常用的方式.

    	spring中的bean都是由不同工厂类创建的.
    

    代理模式

    在不适合或不能直接引用另一个对象的场景,可以用代理模式对被代理的对象进行访问行为的控制.Java的代理模式分为静态代理和动态代理,静态代理是指在编译时就创建好的代理类,例如在源代码中编写的类.动态代理指在JVM运行过程中动态创建的代理类,如JDK动态代理,CDLIB,javaasist等.

    	例如,在Mybatis中getMapper时会通过MapperProxyFactory及配置文件动态生成的Mapper代理对象,代理对象会拦截Mapper接口的方法调用,创建对应方法的MapperMethod类并执行exe cute方法,然后返回结果.
    

    责任链模式

    类似工厂流水线,其中的每个节点完成对对象的某一种处理.

    	Netty框架的处理消息的Pipeline就是采用的责任链模式.
    

    适配器模式

    类似于转接头,将两种不匹配的对象进行适配,也可以起到对两个不同的对象进行解耦的作用.

    	SLF4J可使项目与Log4、logback等具体日志实现框架进行解耦,其通过不同适配器与不同框架进行适配,完成日志功能的使用.
    

    观察者模式

    也可称为发布订阅模式,适用于一个对象某个行为需要触发一系列操作的场景.

    	GRPC中stream流式请求的处理.
    

    构造者模式

    适用于一个对象拥有很多复杂的属性,需要根据不同情况创建不同的具体对象.

    	创建Protocol Buffer对象时,需要用到Builder
    

    Java语言特性

    • 集合类
      主要掌握如何实现.

    • 动态代理与反射
      是java语言的特色,需要掌握动态代理与反射的使用场景.

        ORM框架中会大量使用代理类,PRC调用时使用反射机制调用实现类的方法.
      
    • 数据类型
      也是面试的常见问题.如每种数据类型占用多大空间,数据类型的自动转换与强制转换,基础数据类型与Wrapper数据类型的自动装箱与拆箱等.

    • 对象引用
      (可自行搜索)

    Java基础常考点–Map

    能考查到数据结构,java的基础实现以及对并发问题的处理思路的掌握程度.

    HashMap

    • 通过数组加链表实现.

        数组中的元素为一个链表,通过计算存入对象的hashcode,确认存入位置,用链表解决散列冲突.链表的节点存入的是键值对.
      
    • 填充因子的作用???

    • Map扩容的rehash机制

    • 容量是二的幂次方.

        是为了方便按位与操作计算余数,比求模更快
      
    • 多线程风险的原因

        对线程put时,会在超过填充因子的情况下rehash.HashMap为避免尾部遍历,链表插入采用头插法,多线程场景下可能产生死循环.
      

    ConcurrentHashMap

    • 分段锁思想

                1.7中采用segment分段加锁,降低并发锁定程度.
      
    • CAS自旋锁

               1.8中采用CAS自旋锁(一种乐观锁实现模式)提高性能.但在并发度较高时,性能一般.
      
    • 红黑树

                1.8引入红黑树解决hash冲突时的链表查找问题.在链表长度大于8且总容量大于64时启用.扩容后链表长度小于6时重新转为一般链表.(8,6,64为默认参数)
      

    Java版本特性

    1.8:长期支持版本

    	* Lambda表达式:简洁并行计算
    	* StreamAPI
    	* 方法引用
    	* 接口默认方法:简化掉简单的抽象类
    	* Metaspace替换PremGen
    		M使用本地内存,不在虚拟机中,目的提升对原数据的处理,提成GC效率;以后hotSport与Jrocket合并
    

    1.9-1.10

    	* 模块系统
    	* 默认G1回收器
    	* 接口私有方法
    	* 局部变量判断
    	* Graal编译器
    

    1.11:长期支持版本

    	* ZGC:新的垃圾回收器,大堆内存设计
    	* 字符串API增强
    	* 内建HTTP Client
    

    面试考察点

    1. 基本概念和基本原理
      要求:正确清晰

       * 网络协议4/7层模型的概念
       * TCP协议流量控制的实现原理
      
    2. 实现方法和使用方式

       * HashMap在JDK1.8中的实现方式
       * 单例模式有哪几种实现方式,什么场景该使用静态方法实现,什么场景该使用双检锁实现
      
    3. 经常用到的知识点

       * 常用的Linux命令有哪些,用来解决什么样的问题
      
    4. 实际应用中容易犯错的点

       * ==与equals区别是什么
       * 对象强引用使用不当会导致内存泄露,考察不同引用方式和作用的理解
      
    5. 与面试方向相关的知识点

       * 中间件:存储,网络相关的考察
      

    加分项

    1. 知识点与典型的业务场景关联.

       如,谈到设计模型时,可以讲XX框架在解决XX问题时使用了那种设计模式.
      
    2. 以反例来描述实际场景中误用的危害.

        如,大量使用反射会影响性能.
      
      
    3. 与知识点相关的优化点.

       如,讲到tcp建连和断连时,如遇到洪水攻击或大量TIME_WAIT时,可以调整系统参数预防.
      
      
    4. 与知识点相关的最新技术趋势.

       如,讲到ConcurrentHashMap,可以介绍1.8的改进细节.
       或,讲到HTTP时,能说出HTTP2和QUIC的特点和实现.
      
      
    5. 在了解的前提下,尽量增加回答内容深度.

       如,讲到tcp的滑动窗口时,能讲到流量与拥塞控制,进一步能指出解决拥塞的不同算法.
      
      

    ps.面试官可能会顺着细节追问,回答不上来会适得其反.

    真题汇总

    1. 进程和线程的区别和联系

       从资源占用,切换效率,通信方式等方面解答
      
      
    2. 简单介绍一下进程的切换过程

       线程上下文的切换代价,要回答,切换会保存寄存器,栈等线程相关的现场,需要由用户态切换到内核态,可以用vmstat命令查看线程上下文的切换状况
      
      
    3. 你经常使用哪些Linux命令,主要用来解决哪些问题?

       参考之前操作系统汇总中提到的命令
      
      
    4. 为什么TCP建连需要3次握手而断连需要4次?

       参考之前内容
      
      
    5. 为什么TCP关闭链接时需要TIME_WAIT状态,为什么要等2MSL?

       参考之前内容
      
      
    6. 一次完整的HTTP请求过程是怎样的?

       DNS解析,TCP建连,HTTP请求,HTTP响应等.
      
      
    7. HTTP2和HTTP的区别有哪些?

    8. 在你的项目中你使用过那些设计模式?主要用来解决哪些问题?

    9. Object中的equals和hashcode的作用分别是什么?

    10. final,finally,finalize的区别与使用场景

    11. 简单表述一下Java的异常机制

    12. 先上使用的那个版本jdk,为什么使用这个版本(有什么特色)?

    四、JVM

    • 知识点汇总
    • 知识点详解
      • JVM内存模型
        • 本地方法栈
        • 程序计数器
        • 方法区
      • JMM与内存可见性
      • 类加载与卸载
        • 加载过程
        • 加载机制-双亲委派模式
        • 分代回收
          • 回收算法
    • 考察点
    • 加分项
    • 真题汇总

    知识点汇总

    JVM是Java运行基础,面试时一定会遇到JVM的有关问题,内容相对集中,但对只是深度要求较高.
    JVM

    其中内存模型,类加载机制,GC是重点方面.性能调优部分更偏向应用,重点突出实践能力.编译器优化和执行模式部分偏向于理论基础,重点掌握知识点.
    
    

    需了解
    内存模型各部分作用,保存哪些数据.

    类加载双亲委派加载机制,常用加载器分别加载哪种类型的类.

    GC分代回收的思想和依据以及不同垃圾回收算法的回收思路和适合场景.

    性能调优常有JVM优化参数作用,参数调优的依据,常用的JVM分析工具能分析哪些问题以及使用方法.

    执行模式解释/编译/混合模式的优缺点,Java7提供的分层编译技术,JIT即时编译技术,OSR栈上替换,C1/C2编译器针对的场景,C2针对的是server模式,优化更激进.新技术方面Java10的graal编译器

    编译器优化javac的编译过程,ast抽象语法树,编译器优化和运行器优化.

    知识点详解


    JVM内存模型(Java虚拟机内存模型)

    线程独占:栈,本地方法栈,程序计数器
    线程共享:堆,方法区

    又称方法栈,线程私有的,线程执行方法是都会创建一个栈阵,用来存储局部变量表,操作栈,动态链接,方法出口等信息.调用方法时执行入栈,方法返回式执行出栈.
    
    

    本地方法栈

    与栈类似,也是用来保存执行方法的信息.执行Java方法是使用栈,执行Native方法时使用本地方法栈.
    
    

    程序计数器

    保存着当前线程执行的字节码位置,每个线程工作时都有独立的计数器,只为执行Java方法服务,执行Native方法时,程序计数器为空.
    
    

    JVM内存管理最大的一块,对所有线程共享,目的是存放对象的实例,几乎所欲的对象实例都会放在这里,当堆没有可用空间时,会抛出OOM异常.根据对象的存活周期不同,JVM把对象进行分代管理,由垃圾回收器进行垃圾的回收管理
    
    

    方法区

    又称非堆区,用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器优化后的代码等数据.1.7的永久代和1.8的元空间都是方法区的一种实现
    
    

    回答以上问题是需回答两个要点:

    1. 各部分功能
    2. 是否是线程共享

    JMM与内存可见性

    [外链图片转存失败(img-iomYGzAw-1565101632758)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555596294412.png)]

    JMM是定义程序中变量的访问规则。所有共享变量都存在主内存中共享,每个线程有自己的工作内存,保存的是主内存中变量的工作副本。线程对于变量的读写等操作只能在自己的工作内存中进行,而不能直接对主内存操作。只有从A的工作内存区写回到主内存,B从主内存区读取到自己的工作内存区,才能进一步的操作。由于指令重排序,读写的顺序会被打乱,因此JMM需要提供原子性,可见性,有序性保证.

    [外链图片转存失败(img-3Zyimc80-1565101632759)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1554779864119.png)]

    volatile强制变量的赋值会同步刷新回主内存,强制变量的读取会从主内存中重新加载,保证不同的线程总是能够看到该变量的最新值。

    volatile另一个作用就是阻止指令重排续这样就可以保证变量读写的有序性。

    happens before 原则包括一系列规则比如

    • 程序顺序原则:就是一个线程内必须保证语义串行性
    • 锁规则就是对同把锁的解锁一定要发生在再次加锁之前
    • 此外还包括happens-before原则的传递性
    • 线程的启动中断中止规则等

    类加载与卸载

    class字节码读入到内存,放到方法区内,并创建对应的class对象

    加载过程:加载-链接(验证,准备,解析)-初始化

    [外链图片转存失败(img-ZaeMvGXg-1565101632760)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1554779890785.png)]

    • 加载通过类的完全限定名,查找此类字节码文件,利用字节码文件创建Class对象.

    • 验证确保Class文件符合当前虚拟机的要求,不会危害到虚拟机自身安全.

    • 准备进行内存分配,为static修饰的类变量分配内存,并设置初始值(0null).

      不包含final修饰的静态变量,因为final变量在编译时分配.

    • 解析将常量池中的符号引用替换为直接引用的过程.直接引用为直接指向目标的指针或者相对偏移量等.

    • 初始化主要完成静态块执行以及静态变量的赋值.先初始化父类,再初始化当前类.

      只有对类主动使用时才会初始化,触发条件包括,创建类的实例时,访问类的静态方法或静态变量的时候,使用Class.forName反射类的时候,或者某个子类初始化的时候.

    JVM自带的3种类加载器加载的类,在虚拟机的生命周期中是不会被卸载的,只有用户自定义的加载器加载的类才可被卸载
    
    

    加载机制-双亲委派模式

    [外链图片转存失败(img-MlCj4Pi9-1565101632761)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555596268040.png)]

    双亲委派模式,即加载器加载类时先把请求委托给自己的父类加载器执行,直到顶层的启动类加载器.父类加载器能够完成加载则成功返回,不能则子类加载器才自己尝试加载.
    
    

    优点:

    1. 避免类的重复加载
    2. 避免Java的核心API被篡改

    分代回收:方便垃圾回收

    分代回收基于两个事实:大部分对象很快就不使用了,还有一部分不会立即无用,但也不会持续很长时间.

    堆分代
    年轻代 Dden Survivor1 Survivor2
    老年代 Tenured Tenured Tenured
    永久代 PremGen/MetaSpace PremGen/MetaSpace PremGen/MetaSpace
    • 年轻代主要用来存放新创建的对象,分为Eden区和两个survivor区,大部分对象在Eden区生成,当Eden区满时,还存活的对象会在两个surval区交替保存,达到定次数后对象会晋升到老年代。
    • 老年代用来存放从年轻代晋升而来的存活时间较长的对象。
    • 永久带主要保存类信息等内容。这里的永久代是指对象划分方式不是专指1.7的PremGen或者1 8之后的MetaSpace。

    垃圾回收算法:根据年轻代与老年代的特点JVM提供了不同的垃圾回收算法。

    • 引用计数法:对象被引用的次数确定对象是否再被使用,缺点是无法解决循环引用的问题
    • 标记复制算法:需要from和to两块大小相同的内存空间,对象分配时只在from块进行,回收时把存活对象复制到to块,并清空from块。然后交换两块的分工,from变为to。缺点是内存使用率低。
    • 标记清除法:分为标记对象和清除不再使用的对象两个阶段。缺点是会产生内存碎片。

    年轻代->标记-复制
    老年代->标记-清除:CMS、G1、ZGC

    回收算法

    1.CMS算法
    1.7前主流垃圾回收算法,为标记-清楚算法,优点是并发收集,停顿小.

    [外链图片转存失败(img-0bQHOg5m-1565101632761)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555643016840.png)]

    1. 初始标记会StopTheWorld,标记的对象是root即最直接可达的对象.
    2. 并发标记GC线程和应用线程并发执行,标记可达的对象.
    3. 重新标记第二个StopTheWorld,停顿时间比并发标记小很多,但比初始标记稍长.主要对对象重新扫描并标记.
    4. 并发清理进行并发的垃圾清理.
    5. 并发重置为下一次GC重置相关数据结构.

    2.G1算法
    1.9后默认的垃圾回收算法,特点保持高回收率的同时减少停顿.采用每次只清理一部分,而不是清理全部的增量式清理,以保证停顿时间不会过长
    [外链图片转存失败(img-3ByOThvl-1565101632761)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555643173106.png)]

    其取消了年轻代与老年代的物理划分(改为了逻辑分代),但仍属于分代收集器,算法将堆分为若干个逻辑区域(region),一部分用作年轻代,一部分用作老年代,还有用来存储巨型对象的分区.
    同CMS相同,会遍历所有对象,标记引用情况,清除对象后会对区域进行复制移动,以整合碎片空间.

    • 年轻代回收:
      并行复制采用复制算法,并行收集,会StopTheWorld.
    • 老年代回收:
      会对年轻代一并回收
      初始标记完成堆root对象的标记,会StopTheWorld.
      并发标记GC线程和应用线程并发执行.
      最终标记完成三色标记周期,会StopTheWorld.
      复制/清楚会优先对可回收空间较大的区域进行回收(garbage first)

    只清理一部分的增量式清理,保证每次清理停顿时间不会过长

    可以通过JVM算法设置region的大小,1-32m,还可以设置最大GC停顿时间

    CMS、G1三色标记算法

    3.ZGC
    1.11中提供的高效垃圾回收算法,针对大堆内存设计,可以处理TB级别的堆,可以做到10ms以下的回收停顿时间.

    特点:

    • 着色指针:最大4TB堆(寻址需要42位),剩下22位保存额外信息,对象进行着色标记
    • 读屏障:GC线程和应用线程可能并发修改对象状态的问题,而非简单的STW,只有单个对象处理有概率减速
    • 并发处理:读屏障,大部分不需要STW
    • 基于region:并未进行分代,动态决定大小(G1固定大小),动态创建销毁,更好的管理大对象
    • 内存压缩(整理):CMS原地清理,内存碎片。ZGC同G1清理后移动合并,解决碎片问题。

    [外链图片转存失败(img-QCdDYj8O-1565101632762)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555643934423.png)]

    初始划分为许多小大不用的region

    1. roots标记`标记root对象,会StopTheWorld.
    2. 并发标记对对象指针进行着色进行标记。结合读屏障(解决单个对象的并发问题)与应用线程一起运行标记,最后可能会有StopTheWorld用来处理边缘部分.
    3. 清除会清理标记为不可用的对象.
    4. roots重定位是对存活的对象进行移动,以腾出大块内存空间,减少碎片产生.重定位最开始会短暂StopTheWorld(时间取决于root数量,和重定位集与对象总活动集的比例),用来重定义集合中的root对象
    5. 并发重定位并发标记类似.

    考察点

    1. 深入理解JVM内存模型、JMM

    2. 了解类加载过程,双亲委派机制

    3. 了解内存可见性,JMM保证的几个机制

    4. 了解常用的GC算法特点、执行过程和适用场景

      eg:G1对最大延迟有要求的场合,ZGC 64位系统的大内存服务中

    5. 能够根据业务场景选择合适JVM参数和GC算法

      eg:垃圾回收的并发数,偏向锁的设置

    加分项

    1. 编译器优化

      利用栈上分配,降低GC压力

      编写适合内联优化的代码

    2. 问题排查经验与思路

      解决过线上经FULL GC 的问题

      排查过内存泄露的问题

    3. JVM调优经验和调优思路

      高并发低延迟的场景,如何调整GC参数,降低停顿时间

      针对队列处理机,如何尽可能提高吞吐力

    4. 了解最新的技术趋势(ZGC高效的实现原理和Graalvm实现特点)

    真题汇总

    1. 简单描述一下JVM的内存模型

    2. 什么时候会触发FullGC?

      年轻带晋升时,老年代空间不足

      永久代空间不足

    3. Java类加载器有几种,关系怎样的?

    4. 双请问欧派机制的加载流程是谮言的,有什么好处?

    5. 1.8为首么用Metaspace替换掉PermGen?Meatspace保存在哪?

    6. 编译器会对指令做哪些优化?(简答描述编译器的指令重排)

    7. 简单描述一下volatile可以解决什么问题?如何做到的?

      强制主内存读写同步,防止指令重排序

    8. 简单描述一下GC的分代回收?

    9. G1与CMS的区别?

    10. 对象引用有哪几种,有什么特点?

      强引用,不会被GC

      软引用,内存空间不足时GC

      弱引用,每次GC都回收

      虚引用,和引用队列联合使用,跟踪一个对象被垃圾回收的过程

    11. 使用过哪些JVM调试工具,主要分析哪些内容?

      GMC飞行计数器、堆分析工具MAT、线程分析工具JStack、获取堆信息JMap

    五、并发与多线程

    • 知识点汇总
    • 知识点详解
      • 线程的状态转换
      • CAS与ABA问题
      • Synchronized实现原理
      • AQS与Lock
      • 线程池
        • 线程池参数介绍
    • 考察点
    • 加分项
    • 真题汇总

    知识点汇总

    多线程

    知识点详解


    线程的状态转换

    [外链图片转存失败(img-IFmDuGv2-1565101632762)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555645391502.png)]

    六个状态对应ThreadState的枚举

    CAS与ABA问题

    **CAS:**一种乐观锁的实现,轻量级锁,JUC很多工具类基于CAS

    [外链图片转存失败(img-j3JGycmH-1565101632763)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555646955807.png)]

    线程在读取数据时不进行加锁,准备写回数据时,比较原值是否修改,若未被其它线程修改则写回,若已被修改则重新执行读取流程。

    乐观策略,认为并发操作并不总会发生。比较并写回采用操作系统中的原语,保证不会被中断。

    **ABA问题:**不一定会影响结果,但还是需要防范:增加额外的标位或者时间戳,JUC中有。

    [外链图片转存失败(img-CddBv4tA-1565101632763)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1554780070499.png)]

    Synchronized实现原理

    [外链图片转存失败(img-YyPAZ022-1565101632764)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555647304472.png)]

    保证同一时刻只有一个线程进入临界区:

    对对象进行加锁,对象在内存中分为三块区域(对象头、实例数据、对其填充),对象头中,保存了锁标志位和指向Monitor对象的起始地址。Monitor被某个线程占用后,就会处于锁定状态,Owner指向持有Moniator对象的线程,两个队列,存放进入以及等待获取锁的线程。

    锁优化

    先使用偏向锁,优先同一线程再次获取锁。锁优化会将锁由轻量级升级为重量级

    AQS与Lock

    [外链图片转存失败(img-s0hGoVgM-1565101632764)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555647844234.png)]

    AQS队列同步器,实现Lock的基础。state标志位,1有线程占用,其他需要进入同步队列等待。同步队列是一个双向链表,当获得锁的线程需要等待某个条件时,需要进入等待队列。可以有多个,当条件满足时,可以重进入同步队列,进行获取锁的竞争。

    Re entrant Lock:基于AQS。有公平锁,非公平锁,差别在于新来的线程有没有可能比已经等待的更早获得锁。独占锁。Semaphore,共享锁。

    线程池

    复用线程,避免线程频繁的创建与销毁。

    • NewFixedThreadPool 固定大小线城池,固定线程数,无界队列.适用于任务数量不均匀的场景,对内存压力不敏感,但系统负载敏感的场景.
    • NewCachedThreadPool cached线程池,无限线程数,适用于要求低延迟的短期任务场景.
    • newSingleThreadPool 单个线程的固定线程池,适用于保证异步执行顺序的场景.
    • newScheduledThreadPool Scheduled线城池,适用于定期执行任务场景,支持固定频率和固定延迟.
    • newWorkStealingPool 工作窃取线程池,使用ForkJoinPool,多任务队列的固定并行度,适合任务执行时长不均匀的场景.

    线程池参数介绍

    线程池构造方法:除newWorkStealingPool

    ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepaAliveTime,TimeUnit timeUnit,BlockQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExceptionHandler rejectedHandler) //ThreadPoolExecutor构造方法
    

    corePoolSize核心线程数,也可理解为最小线程数
    maximumPoolSize最大线程数
    keepaAliveTime非核心线程非活跃存活时间长度,线程闲置超过空闲时间时,被销毁
    timeUnit存活时间单位,枚举等

    ​ 可以通过allowedCoreThreadTimeout方法允许核心线程被回收

    workQueue缓冲队列,

    ​ ArrayBlockingQueue(capacity):有界队列,队列有最大限制

    ​ LinkedBlockingQueue:无界队列,队列不限制容量

    ​ SynchronousQueue:同步队列,内部没有缓冲区
    threadFactory 设置线程池工厂方法,可用来对线程的一些属性定制,一般使用默认即可,线程名,优先级等
    rejectedHandler线程池满时拒绝策略,

    ​ Abort:默认,满时,提交新任务会抛出异常

    ​ Discard:提交失败时,对任务直接丢弃

    ​ CallerRuns:提交失败时,由提交任务的线程直接执行提交任务

    ​ DiscardOldest:丢弃最早提交的任务

    每种线程具体创建方法

    • NewFixedThreadPool 固定大小线城池,核心、最大线程数指定的,无界队列LinkedBlockingQueue
    • NewCachedThreadPool cached线程池,核心线程数0,最大整数Int的最大值,SynchronousQueue,只要没有空闲的线程,就会新建。
    • newSingleThreadPool 单个线程的固定线程池,线程数设置为1
    • newScheduledThreadPool Scheduled线城池,DelayedQueue按延迟时间获取任务的优先级队列

    线程池任务执行流程

    提交任务execute,submit(可以返回一个对象,了解任务的执行情况 ,可以取消任务的执行,获取执行结果,执行异常,最终也是通过execute执行的)

    [外链图片转存失败(img-9QI1gaTg-1565101632764)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555649924146.png)]

    先判断最大线程数

    JUC常用工具
    JUC常用工具

    第一格,基本数据类型的原子类。

    unsafe类:底层工具类,提供了类似C的指针操作,提供CAS功能,所有方法都是native

    Semaphore:允许多个线程共享资源,适用限制使用共享资源,100个车,20个车位,最多20个有车位

    写饥饿:多线程读写时,读线程访问非常频繁,导致总是有读线程占用资源,写线程很难加上写锁。

    CompletableFuture:可以同时执行两个异步任务,然后对执行结果进行合并处理

    ForkJoinPool:分治思想+工作窃取(有效平衡任务执行时间长短不一的场景)

    考察点

    1. 理解线程的同步与互斥原理

       临界资源与临界区的概念
       重量级锁,轻量级锁,自旋锁,偏向锁,读写锁,重入锁的概念
      
      
    2. 掌握线程安全相关机制

       CAS,synchronized,lock同步方式的实现原理
       ThreadLocal是线程独享的局部变量,使用弱引用的ThreadLocalMap保存ThreadLocal变量
      
      
    3. 了解JUC工具的使用场景与实现原理

       ReentrantLock,ConcurrentHash,LongAdder的实现方式
      
      
    4. 熟悉线程池的原理,使用场景,常用配置

      大量短期的任务,适合使用Cached;系统资源紧张,固定线程池;
      慎用无界队列,可能会有OOM的风险
      
      
    5. 理解线程的同步与异步,阻塞与非阻塞

       同步异步:任务是否在同一个线程中执行
       阻塞非阻塞:异步执行任务时,线程是否会阻塞等待结果,还是会继续执行后面的逻辑
      
      

    加分项

    1. 结合实际项目经验或实际案例介绍原理

      eg:项目中有一个需要高吞吐量的场景,使用了Cache的线程池

    2. 解决多线程问题的排查思路与经验

    3. 熟悉常用的线程分析工具与方法

       如Jstack分析线程的运行状态,查找锁对象的持有状况
      
      
    4. 了解Java8对JUC的增强

       用LongAdder替换AtomicLong,更适合并发度高的场景
      
      
    5. 了解Reactive异步编程思想,被压的概念与应用场景

    真题汇总

    1. 如何实现生产者消费者模型?

       可利用锁,信号量,线程通信,阻塞队列等方法实现
      
      
    2. 如何理解线程的同步与异步,阻塞与非阻塞?

    3. 线程池处理任务的流程?

    4. wait与sleep有什么不同?

       wait是Object方法,sleep是Thread方法
       wait会释放锁,sleep不会
       wait要在同步块中使用,sleep在任何地方使用
       wait不需要捕获异常,sleep需要
      
      
    5. Synchronized与ReentrantLock有什么不同,各适用什么场景?

    6. 读写锁适用与什么场景,ReentrantReadWriteLock是如何实现的?

      读写锁:适合读并发多,写并发少的场景,另外一个可以的是CopyOnWrite
      
      
    7. 线程之间如何通信?

       wait/notify机制
       共享变量的synchronize&lock同步机制
      
      
    8. 保证线程安全的方法有哪些?

       CAS,synchronized,lock,ThreadLocal
      
      
    9. 如何尽可能提高多线程并发性能?

       减少临界区范围
       使用ThreadLocal
       减少线程切换
       使用读写锁或CopyOnWrite
      
      
    10. ThreadLocal用来解决什么问题,ThreadLocal是如何实现的?

      不是用来解决多线程共享变量问题,而是用来解决线程数据隔离问题
      
      
    11. 死锁的产生条件,如何分析线程是否有死锁?

    12. 在实际工作中遇到过什么样的并发问题,如何发现排查并解决的?

    六、数据结构与算法

    • 知识点汇总
    • 知识点详解
      • 数据结构
          • 二叉搜索树
          • 平衡二叉树
          • 红黑树
          • B树
          • B+树
      • 算法
        • 字符串匹配问题
        • TopK问题
          • 找出N个数中最小的k个数(N非常大)
          • 从N有序队列中找到最小的K个值
        • 常用算法介绍
    • 面试考察点
    • 加分项
    • 真题汇总

    知识点汇总

    数据结构
    算法

    知识点详解


    数据结构

    二叉搜索树

    二叉搜索树

    每个节点都包含一个值,每个节点至多有两棵子树,左孩子小于自己,右孩子大于自己,时间复杂度是O(log(n)),随着不断插入节点,二叉树树高变大,当只有左(右)孩子时,时间复杂度变为O(n).

    平衡二叉树

    保证每个节点左右子树高度差绝对值不超过1.
    比如,AVL树在插入和删除数据是经常需要旋转以保持平衡.适合插入删除少场景.

    红黑树

    红黑树

    非严格平衡二叉树,更关注局部平衡,而非总体平衡,没有一条路径比其他路径长出两倍,接近平衡,减少了许多不必要的旋转操作,更加实用.
    特点:

    1. 每个节点不是红就是黑
    2. 根节点是黑色
    3. 每个叶子都是黑色空节点
    4. 红色节点的子节点都是黑的
    5. 任意节点到其叶节点的每条路径上存在的黑色节点数量相同.
    B树

    B树

    适用于文件索引,优先减少磁盘IO次数,最大子节点称为B树的阶

    关键字分布在整棵树中,一个关键字只出现在一个节点中,搜索可能在非叶节点停止

    m阶b树特点:

    1. 非叶子节点最多有m棵子树
    2. 根节点最少有两棵子树
    3. 非根非叶节点最少有m/2棵子树
    4. 非子叶节点保存的关键字个数,为该节点子树个数减一,有三个子树,必定包含两个关键字
    5. 非叶子节点的关键字大小有序,eg 37 51
    6. 关键字的左孩子都小于该关键字,右孩子都大于关键字
    7. 所有叶节点都在同一层
    8. 采用二分查找法
    B+树

    B+树

    定义与b树基本相同,
    区别:

    1. 节点有多少关键字,有多少子树
    2. 关键字对应子树的节点都大于等于关键字,子树中包括关键字自身
    3. 所有关键字都出现在叶节点中
    4. 所有叶节点都有指向下一个叶节点的指针
    5. 搜索时只会命中叶节点,叶子节点相当于数据存储层,保存关键字对应的数据,非叶节点只保存关键字与指向叶节点的指针,非叶节点B+树小很多(只保存了指针)

    B+树比B树更适合做索引:

    1. 叶节点之间有指针相连,B+树跟适合范围检索
    2. 由于非叶节点只保留关键字和指针,B+树可以容纳更多的关键字,降低树高,磁盘IO代价更低
    3. B+树查询过程稳定,必须由根节点到叶节点,所有关键字查询路径相同,效率相当.Mysql数据的索引就提供了B+树的实现

    B*树
    在B+树的非叶节点上增加了指向同一层下一个非叶节点的指针

    算法

    字符串匹配问题

    先于面试官交流,询问是否有其他要求

    Example:判断给定字符串中的符号是否匹配
    解题思路:
    1. 使用栈
    2. 遇到左括号入栈
    3. 与右括号出栈,判断出栈括号是否成对
    
    private static fianl Map<Character,Character> brackets = new HashMap<>();
    static{
        brackets.put(')','(');
        brackets.put(']','[');
        brackets.put('}','{');
    }
    public static boolean isMatch(String str){
        if(str==null){
            return false;
        }
        Stack<Character> stack = new stack<>();
        for(char ch : str.toCharArray()){
            if(barckets.containsValue(ch)){
                stack.put(che);
            } else if (brackets.contiansKey(ch)){
                if(stack.empty() || stack.pop() != bracjets.get(ch)){
                    return false;
                }
            }
        }
        return stack.empty();
    }
    
    

    解题技巧
    认真审题:

    1. 单模匹配还是多模匹配
    2. 时间复杂度空间复杂度是否有要求
    3. 明确期望的返回值,如,多匹配结果的处理

    解题思路

    1. 单模匹配:BM,KMP算法
    2. 多模匹配:Tire树
    3. 前缀或后缀匹配
    4. 可以借助栈,树等数据结构

    TopK问题

    找出N个数中最小的k个数(N非常大)

    解法:

    1. 用前K个数创建大小为K的大根堆
    2. 剩余的N-K个数与堆顶进行比较,小于堆顶,则替换。

    时间复杂度:O(N*log(K))
    优点:不用在内存中读入所有元素,适用于非常大的数据集

    从N有序队列中找到最小的K个值

    解法:

    1. 用N个队列的最小值组成大小为K的小根堆
    2. 取堆顶值
    3. 将堆顶值所在队列的下个值加入堆(与堆中最大值比较,若该值大于最大值则可停止循环)
    4. 重复步骤2,直到K次

    时间复杂度:O((N+K-1)*log(K))

    常用算法介绍

    常用算法介绍

    ​ 分治:快排,归并排序

    面试考察点

    • 了解基本数据结构及特点
      • 如,有哪些二叉树,各有什么特点
    • 表/栈/队列/数需要熟练掌握,深刻理解使用场景
      • 红黑树适合用搜索,B+数适合做索引
    • 了解常用的搜索/排序算法,以及复杂度和稳定性
      • 特别是快速排序和堆排序
    • 了解常用的字符串处理算法
      • 如,BM使用后缀匹配进行字符串匹配
    • 能够分析算法实现的复杂度
      • 特别是时间复杂度
    • 了解常用算法分类,解决问题的实录和解决哪类问题

    加分项

    • 能够将数据结构与实际使用场景结合
      • 如,介绍红黑树时,结合TreeMap的实现,介绍B+数时,结合Mysql中的索引实现
    • 不同算法在业务场景中的应用
      • 如,TopK算法在热门排序中的应用
    • 面对模糊的题目能够后沟通确认条件和边界
    • 书写算法代码前,先讲一下解题思路
    • 能够发现解答的一些问题,给出改进思路

    真题汇总

    • 各种排序算法的实现和复杂度,稳定性
    • 二叉树的前中后序遍历
    • 翻转句子中单词的顺序
    • 用栈模拟队列(或用队列模拟栈)
    • 对10亿个数进行排序,限制内存为1G
      • 采用分治的思路
    • 去掉(或找出)两个数组中重复的数
      • 排序和hash两种思路
    • 将一颗二叉树转换成其镜像
    • 确定一个字符串中的括号是否匹配
    • 给定一个开始词,一个结束词,一个字典,如何找到从开始词到结束词的最短单词接龙
      • 考虑使用深度优先算法
    • 如何查找两个二叉树的最近公共祖先
      • 递归与非递归皆可实现

    七、常用工具集

      • 知识点汇总
    • 知识点详解
      • JMC(Java Mission Control)
      • btrace
      • 其他常用工具
      • Git
      • 常用Linux分析工具
    • 考察点
    • 加分项
    • 真题汇总

    知识点汇总

    常用工具

    知识点详解


    JMC(Java Mission Control)

    1.7提供的图形化JVM分析与监控工具
    [外链图片转存失败(img-hI3EamWI-1565101632766)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555666380171.png)]

    • JVM浏览器

      • 可列出正在运行的Java程序JVM,每个JVM实例叫做一个JVM连接,使用JDP(Java Discover Protocol),可以连接到本地和远程运行的JVM
    • JMX(Java Management Extensions)

      • 可以管理并监控JVM,通过对MBean的管理可以实时收集JVM信息,例如,类使用信息,堆使用情况,CPU负载,线程信息等,以及其他可以通过MBean管理的运行时属性
    • JFR(Java Flight Recorder)

      • 提供了能够深入JVM内部,能看到运行时状态的能力,是个非常强大的性能profile工具,适合对程序进行调优和问题排查.主要对运行事件进行采集,可以通过指定采集的事件和频率,收集非常全面的的数据信息
      • GC:不同阶段及耗时情况,停顿时间,分代大小

      b-trace

      JVM实时监控工具,基于动态字节码修改技术,实现对运行中的Java程序跟踪和替换,可在不重启JVM的情况下,监控系统运行情况,获取JVM运行时的数据信息,如,方法参数,返回值,全局变量,堆栈信息等

    [外链图片转存失败(img-G5DrxP45-1565101632766)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555666734520.png)]

    注意事项:

    1. 不恰当的使用会导致JVM崩溃
    2. btrace操作会持续JVM运行期间
    3. 通过JVM参数,取消btrace安全限制

    其他常用工具

    作用与特点
    jps 查看Java进程信息:进程id,主类名称,主类全路径
    jmap 查看JVM中对象的统计信息:内存占用,实例个数,对象类型,可以堆分析
    jstat 实时监控JVM的资源和性能:类加载情况,内存容量、使用量,GC次数、时间
    jstack 查看JVM线程栈信息:线程名称、序号、优先级、线程状态、锁状态
    jinfo 动态查看,调整JVM参数
    jcmd 1.7提供的综合工具:向JVM发送诊断命令,包含jmap、jstat、jstack
    jconsole,jprofiler,jvisualvm 监控与性能分析.建议使用JMC代替

    实际应用场景

    1. 希望打印GC详细日志,发现未开启时,可通过jinfo开启print_gc_details,动态生效
    2. 分析内存泄漏风险时,使用jmap或jcmd定期获取堆对象的统计信息,发现定期增长的可疑对象
    3. 发现所有服务都存在耗时较高的情况,可以使用jstat检查gc回收状况,看看是不是gc停顿耗时过高
    4. 遇到某个服务卡死或停止处理时,可用jstack查看线程栈,是否存在多个线程为block状态,产生了死锁
    5. 当服务上线后没有达到预期,可用jmc分析JVM运行信息,看看哪些热点方法可以优化,哪些线程竞争可以避免

    Git

    Git常用命令

    Git常用工作流
    Git工作流

    常用Linux分析工具

    作用与特点
    vmstat 进程,虚拟内存,页面交换,IO读写,CPU活动
    instat&iotop 系统IO状态信息
    ifstat&iftop 实时网络流量监控:能看到那个ip在霸占网络流量
    netstat 查看网络相关信息,各种网络协议套接字状态
    dstat 全能型实时系统信息统计:CPU、内存、网络、负载、系统磁盘信息
    strace 诊断,调试程序的系统调用:JVM执行native方法时进行调试
    GDB 程序调试,JVM因未知原因崩溃,coredump分析
    lsof 查看系统当前打开的文件信息
    tcpdump 网络抓包工具:服务之间的调用
    traceroute 网络路由分析工具:本地和目标计算机之间的所有路由,经过公网的服务之间网络问题排查

    考察点

    • 了解常用的JVM分析工具
      • 分析线程死锁可用jstack
      • 内存溢出可用jmap:堆中占用最大的对象类型
      • 分析程序性能可用jmc中的jfr
    • 掌握Git的常用操作与工作流
      • merge命令(提交commit来合并修改)与rebase命令(修改提交历史记录)的区别
      • 各种工作流的优缺点
    • 了解Linux系统下常用的分析工具
      • 磁盘写入用时较高,可用iostat分析磁盘io情况
      • 不能确定问题,可用strace对文件写入的系统调用进行分析
      • 定位CPU负载较高的原因,可用top与jstack结合分析

    加分项

    • 能够主动出击体现知识广度
    • 能够体现使实战能力

    实战重点说明

    询问线上问题

    遇到过单机请求耗时较高的问题,通过JMC的飞行记录器采样分析,发现写log日志时,线程竞争非常激烈,很多线程在等待写锁时耗时非常大。

    进一步通过iostate排查发现,util利用率比较高,最后定位是磁盘出现了问题。解决方法,一方面更换磁盘来解决问题,另一方面对写竞争比较激烈的日志文件,使用了异步log机制。

    介绍自己开发的项目:

    1.上线前使用JMC做了性能profile,发现并优化了某些问题

    2.对两个不同方案使用JMH测试,验证了两个方案的性能

    真题汇总

    • 排查JVM问题有哪些常用工具?(你曾遇到过什么问题,如何排查,如何解决的)
    • Git合并代码由哪些方法?有什么区别?
    • Git与SVN有哪些差异?
    • 你所在的吐纳对项目开发使用什么样的工作流?有什么优点?

    JMC,TCPdump,Strace

    八、必会框架1️⃣一Spring全家桶

    • 知识点汇总
    • 知识点详解
      • Spring
        • Spring中的基本概念
        • Spring框架
        • Spring机制与实现
        • Spring应用
        • Spring Context初始化流程
        • Spring中Bean的生命周期
        • Spring扩展接口
      • SpringBoot

    知识点汇总

    常用框架

    知识点详解

    Spring

    Spring中的基本概念

    [外链图片转存失败(img-TAawpDbs-1565101632767)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555670082098.png)]

    • IOC/DI
      • 对象的属性由自己创建,为正向流程,而由Spring创建,为控制反转.
      • DI(依赖注入)为实现IOC的一种方式,通过配置文件或注解包含的依赖关系创建与注入对象.
      • 正向流程导致了对象与对象之间的高耦合,IOC可以解决对象耦合的问题,有利于功能的复用
    例如,招聘中,公司按岗位要求安排人选为正向流程,反之,由第三方猎头匹配岗位和候选人,并向公司推荐,则为控制反转
    
    
    • Context&Bean
      • 所有由Spring创建,管理,用于依赖注入的对象,称为Bean
      • 所有Bean创建并完成依赖注入后,都会放入Context上下文中进行管理
    • AOP(Aspect Oriented Programming 面向切面编程)
      • 以功能进行划分,对服务顺序执行流程中的位置进行横切,完成各服务共同需要实现的功能

    Spring框架

    [外链图片转存失败(img-oh1hG9gQ-1565101632768)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555670118767.png)]
    重点了解一下几点

    • Core
      • Spring组件的核心
    • Beans和Context
      • 实现IOC/DI的基础
    • Web
      • 包括SpringMVC是Web服务的控制层实现
    • AOP
      • 面向切面编程

    Spring机制与实现

    Spring机制与实现

    Spring应用

    Spring应用

    • @Component和@Bean的区别

      Component在类上使用,表明其是组件类,需要Spring为这个类创建bean

      Bean使用在方法上,告诉Spring这个方法返回一个bean对象,需把返回的对象注册到Spring应用的上下文中

    • 设置类,autowried、qualilfier 以及bytype、byname不同的自动装配机 制

    • Web类知道就行

    Spring Context初始化流程

    三种:xml配置的、Springboot的、web的ApplicationContext

    [外链图片转存失败(img-91cSprf7-1565101632769)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555677689877.png)]

    [外链图片转存失败(img-H3C7CbEB-1565101632770)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555677702922.png)]

    1. prepareRefresh();对刷新进行准备,包括设置开始时间,设置激活状态,初始化Context中的占位符,子类根据其需求执行具体准备工作,而后再由父类验证必要参数

    2. obtianFreshBeanFactory();,刷新并获取内部的BeanFactory对象

    3. prepareBeanFactory(beanFactory);,对BeanFactory进行准备工作,包括设置类加载器和后置处理器,配置不能自动装配的类型,注册默认的环境Bean

    4. postProcessBeanFactory(beanFactory);为Context的子类提供后置处理BeanFactory的扩展能力,如想在bean定义加载完成后,开始初始化上下文之前进行逻辑操作,可重写这个方法

    5. invokeBeanFactoryPostProcessors(beanFactory);,执行Context中注册的BeanFactory后置处理器,有两张处理器,一种是可以注册Bean的后置处理器,一种的针对BeanFactory的后置处理器,执行顺序是先按优先级执行注册Bean的后置处理器,而后再按优先级执行针对BeanFactory的后置处理器

       SpringBoot中会进行注解Bean的解析,由ConfigurationClassPostProcessor触发,由ClassPathDefinitionScanner解析,并注册到BeanFactory
      
      
    6. registerBeanFactoryProcessor(beanFactory();,按优先级顺序在BeanFactory中注册Bean的后置处理器,Bean处理器可在Bean的初始化前后处理

    7. initMessageSource();初始化消息源,消息源用于支持消息的国际化

    8. initApplicationEventMuticaster();初始化应用事件广播器,用于向ApplicationListener通知各种应用产生的事件,标准的观察者模型

    9. onRefresh();,用于子类的扩展步骤,用于特定的Context子类初始化其他的Bean

    10. registerListeners();,把实现了ApplicationListener的类注册到广播器,并对广播其中早期没有广播的事件进行通知

    11. finishBeanFactoryInitialization(beanFactory);,冻结所有Bean描述信息的修改,实例化非延迟加载的单例Bean

    12. finishRefresh();,完成上下文的刷新工作,调用LifecycleProcessor.onRefresh(),以及发布
      ContextRefreshedEvent事件

    13. resetCommonCaches();在finally中执行该步骤,重置公共的缓存,如ReflectionUtils中的缓存,
      AnnotationUtils等

    更详细可见:SpringBoot源码分析之Spring容器的refresh过程

    Spring中Bean的生命周期

    [外链图片转存失败(img-9XhQo5cX-1565101632770)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555677947778.png)]

    Spring扩展接口

    扩展接口 作用
    BeanFactoryPostProcessor 处理Bean前,对BeanFactory进行预处理,描述信息加载完未初始化
    BeanDefinitionRegistryPostProcessor 可添加自定义的Bean,根据scope创建新的代理bean
    BeanPostProcessor 支持Bean初始化前后的处理
    ApplicationContextAware 可以获得ApplicationContext及其中的Bean,动态获取bean
    InitializingBean 在Bean创建完,所有属性注入后执行,对自动装配的属性验证
    DisposableBean 在Bean销毁前执行,回收工作
    ApplicationListener 用于监听产生的应用事件

    前三个可以通过实现ordered或者priordered接口指定执行顺序,priorityordered先于ordered

    SpringBoot

    SpringBoot

    九、必会框架2️⃣Netty与RPC与ORM

    • 知识点汇总
    • 知识点详解
      • Netty
        • Netty线程模型
      • RPC
        • 开源RPC框架介绍
      • Mybatis
        • Mybatis处理流程
    • 面试考察点
    • 加分项
    • 真题汇总

    知识点汇总

    知识点详解

    Netty

    在这里插入图片描述

    Netty线程模型

    [外链图片转存失败(img-r6S1Rete-1565101632771)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555678637956.png)]

    在这里插入图片描述

        其中ChannelPiepline的设计模型采用的是Handler组成的责任链模型
    
    

    更详细介绍请看这可能是目前最透彻的Netty原理架构解析

    添加~~~

    RPC

    Remote Procedure Call(远程过程调用))
    [外链图片转存失败(img-1KD2N1IR-1565101632771)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555678719460.png)]

    开源RPC框架介绍

    Dubbo 打包(double) Motan gRPC
    服务治理型框架 多种负载均衡策略 自动服务注册治理 可视化服务治理 基于TCP私有协议,Netty 轻量级服务治理框架 支持多语言 支持ServiceMesh方案 拓展能力强大 基于TCP私有协议,Netty 支持多语言交互 提高服务治理拓展 支持流式调用 支持服务端推送 基于HTTP2.0

    Mybatis

    在这里插入图片描述

    Mybatis处理流程

    [外链图片转存失败(img-3pfgDxvK-1565101632772)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555679091809.png)]

    面试考察点

    • 掌握Spring的IOC,AOP的概念与实现
    • 掌握Spring的Context创建流程和Bean的生命周期
    • 了解Spring常见注解的作用与使用方法
    • 了解SpringBoot的相关知识点
    • 掌握Netty的线程处理模型
    • 知道常用RPC框架的特点
    • 了解Mybatis和Hibernate的实现原理

    加分项

    • 阅读过源码,了解实现细节和思路,结合断点调试的方法
    • 不仅会应用,还能够理解设计理念,设计思想
    • 了解最新实现或方向
    • 有实际优化经验,例如netty调优,尽量减少io线程占用,把可以后置的处理放到业务线程池中

    真题汇总

    • SSH与SSM框架组合的区别
      • SpringMVC与Struct的区别,Mybatis与Hibernate的区别
    • 描述一下SpringContext的初始化流程
    • 简单介绍一下Bean的生命周期与作用域
    • Spring配置中的placeholder占位符是如何替换的,有什么办法实现自定义的配置替换
      • 通过BeanFactoryPostProcessor处理,
      • 自定义处理可以扩展PropertyPlaceholderConfigurer或PropertySourcesPlaceholderConfigurer
    • SpringMVC工作流程
      • 从HandlerMapping查找handler,执行handler,执行完成返回ModelAndView,由视图解析返回视图,再由渲染器进行渲染
    • Spring如何解决循环依赖
      • 构造器循环依赖和setter循环依赖两部分解答,构造器通过使用创建Bean中的标识池判断是否产生了循环创建,setter通过引入ObjectFactory解决
    • Bean构造方法,@PostConstuct注解,InitiatingBean,init-method的执行顺序
    • Netty中有哪些重要的对象,它们之间的关系是什么
      • Channel,Socket,NioEventLoop,ChannelPipeline等
    • RPC与HTTP的区别,以及相对应的使用场景
      • 使用方式:HTTP使用C/S(client)方式调用,RPC使用动态代理方式调用
      • 请求模型:HTTP经过dns解析,4/7层代理等中间环节,rpc点对点直连
      • 服务治理:rpc丰富的服务治理功能,熔断,负载均衡
      • 语言友好:HTTP对跨语言之间的更加友好
    • RPC的交互流程是怎样的
    • 介绍一下Mybatis的缓存机制
    • Mybatis如何配置动态Sql,有哪些动态标签

    十、缓存(Redis与Memcache)

    • 知识点汇总
    • 知识点详解
      • MC的内存结构
      • Redis
        • 功能
        • 持久化
        • 淘汰策略
      • Redis数据结构
      • 缓存常见问题
    • 面试考察点
    • 加分项
    • 真题汇总

    知识点汇总

    缓存是高并发场景下,提升热点数据访问性能的手段
    在这里插入图片描述

    知识点详解

    MC的内存结构

    [外链图片转存失败(img-YpKQLgqg-1565101632773)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555679749069.png)]

    添加~~~

    Redis

    在这里插入图片描述

    功能

    bitmap支持按位存取信息,可用于实现bloomfilter
    hyperLogLog提供不精确的去重统计功能,适合用作大规模数据的去重统计
    geospatial可用于保存地理位置,并作位置距离计算或根据半径计算位置等
    Sub/Pub订阅发布功能,可用于简单的消息队列
    pipeline可批量执行一组指令,一次性返回全部结果,另一种方式是使用脚本
    事务功能是串行执行,但失败不会回滚

    持久化

    • RDB
      • 将数据集以快照形式写入磁盘,通过fork子进程执行,采用二进制压缩存储
      • redis数据保存在单一文件中,适合用作灾害备份,
      • 缺点:快照写入磁盘之前宕机会丢失数据,保存快照时会短时间服务停顿
    • AOF
      • 以文本日志的形式,记录redis的每一个操作
      • 追加模式,灵活同步策略以保持同步(每秒,每次操作,不同步)
      • 缺点:磁盘文件与RDB方式比大,效率低于RDB

    高可用

    三级能哨兵监视redis主服务器状态,主挂掉,选出新主

    master选举

    1. slave的priority越低,优先级越高
    2. 同等情况,slave复制的数据越多
    3. id越小,容易被选中

    集群中sentinel也会多实例部署,之间通过rift协议保证自身的高可用

    redis-claster使用分片机制,16384(2^10)个slat,每个负责一部分,通过slave节点保障数据冗余

    淘汰策略

    voltile-对设置的生存时间的key进行lru,最小生存时间,随机剔除
    allkeys-则是对所有key
    no-eviction则是不进行剔除,读取正常,写入则会报异常

    Redis数据结构

    [外链图片转存失败(img-lfHZnttW-1565101632773)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555680619319.png)]

    使用字典存储不同类型的数据,如图中的dict HT,字典由一组dictEntry组成(指向K-V的指针,及指向下一个dictEntry的指针)。所有对象都被封装为redisObject(包括了对象的类型与具体对象的存储方式)

    • sting类型,最常使用的,通过SDS(Simple Dynamic String)实现

      SDS类似ArrayList可以通过预分配冗余空间,减少内存频繁分配

    • list由ziplist压缩链表和linkedlist双链表实现

      • ziplist存储在连续位置上,存储效率高,不利于修改操作,适用于数据较少的情况
      • linkedlist再插入节点上复杂度低,但内存开销大,节点地址不连续,容易产生内存碎片
      • 3.2后增加了quicklist,其本身是双向无环链表,每个节点是ziplist
    • hash由ziplist和hashtable实现

      • hash中的K/V字符串长度小于64B且hash长度小于512时使用ziplist,超过时使用hashtable
    • set由hashtable和intset

      • 当set中的值都为数值且set长度小于512时使用intset,否则使用hashtable
    • sorted set有序集合(zset)由ziplist和skiplist实现

      • 当sorted set中元素长度小于64B且zset长度小于128时使用ziplist,超过时会使用skiplist

    redis内存分配采用jemalloc,将内存划分为small,large,huge三个范围,并在其中划分了不同大小的内存块,存储数据时选择大小合适的内存块进行存储,有利于减小内存碎片

    缓存常见问题

    缓存问题 产生原因 解决方案
    缓存更新方式 数据变更,缓存时效性 同步更新,失效更新,异步更新,定时更新
    缓存不一致 同步更新失败,异步更新 增加重试,异步补偿任务,最终一致
    缓存穿透 恶意攻击 空对象缓存,bloomfilter过滤器
    缓存击穿 热点key失效 互斥更新,随机退避,差异失效时间
    缓存雪崩 缓存宕机 快速失败熔断,主从模式,集群模式
    1. 失效时继续使用数据,由异步更新数据,避免了失效瞬间的空窗期。纯异步:定时更新

    2. 缓存穿透,一直用不存在的用户id频繁请求接口,查询缓存不命中,穿透db查询依然不命中,大量db查询

      不存在的用户,缓存中保存空对象进行标记,可能会导致大量无用数据

      bloomfilter,存在性检测,不存在则数据一定不存在;存在则实际可有可无

    3. 缓存击穿,某个热点数据失效时,大量针对这个数据的请求会针对到数据源

      互斥锁更新,同一个进程,针对同一个数据不会并发请求db,减小db的压力

      随机退避,失效时随机sleep一个很短的时间,再次查询如果失败,才执行更新

      差异失效时间,针对多个热点,避免同一时刻失效

    面试考察点

    • 了解缓存的使用场景,不同类型缓存的使用方式
      • 对db热点数据进行缓存能减轻db压力,对热点服务进行缓存能提高服务并发性能
      • 单纯的K/V缓存场景可以使用MC,需要缓存特殊数据结构时可以使用Redis
      • 如,缓存视频播放列表可以使用redis的list缓存,计算排行榜数据时可以使用zset
    • 掌握MC和Redis的常用命令
    • 了解MC和Redis在内存中的存储结构
    • 了解MC和Redis得数据失效方式和提出策略
      • 如主动触发的定期删除,被动触发的延期删除
    • 了解Redis的持久化,主从同步与cluster部署的原理
      • 如RDB与AOF的实现方式与区别

    加分项

    • 结合实际应用场景来介绍缓存的使用
      • 如调用后端服务接口获取信息时,可使用本地+远程的多级缓存
      • 动态排行榜,使用zset
    • 有过分布式缓存设计和应用经验
      • 什么场景使用了redis,使用了什么样的数据结构,解决了那类的问题
      • 使用MC时,根据预估值的大小,调整MC slave的分配参数
    • 了解缓存使用中可能出现的问题
      • redis 单线程处理,避免耗时较高的单个请求任务,防止相互影响
      • 避免和其他CPU密集型的进程部署在同一台机器
      • 禁用内存交换,防止redis的缓存数据交互在硬盘上,影响性能
    • 知道Redis的典型应用场景
      • 实现分布式锁,
      • 使用bit-map实现bloom filter
      • 使用 进行uv统计
    • 知道Redis的新特新
      • 5.0stream相较Sub/Pub功能可将未消费的信息进行缓存类似(kafka)

    真题汇总

    • Redis和Memcache有什么区别,该如何选择?
    • 你用到那些Redis的数据结构,在什么场景下?
    • Redis有哪些持久化方式,有什么区别?
    • Redis的失效机制是怎样的,Redis有哪些淘汰策略?
    • 如何保证Redi的高并发和高可用?
      • 高并发:主从读写分离,多从库,多端口实例以及cluster集群部署
      • 高可用:sentinel保证主库宕机时,重新选住并完成从库的变更
    • 如何使用Redis实现延时队列,如何使用Redis实现分布式锁?
      • 可使用sortedset实现延迟队列,使用时间戳做score,消费方使用zrange by score命令获取指定延迟时间之前的数据.
      • 可是使用setnx设置key,返回1则获取锁成功,返回0则获取锁失败,需要同时使用px参数设置超时时间,防止获取锁的实例宕机后产生死锁,严格场景下使用red log方案,单比较复杂

    十一、消息队列与数据库

    • 知识点汇总
      • 消息队列
        • RabbitMQ
        • ActiveMQ
        • RocketMQ
        • kafka
      • 数据库
        • 关系型数据库
        • NoSQL(Not Only SQL)
        • NewSQL
      • 数据库范式
    • 知识详解
      • Kafka架构
      • Kafka消息生产/生产流程
      • 数据库事务
        • 事务特性
        • 事务并发问题与隔离级别
        • 事务分类
      • MySQL
        • 索引
        • MySQL调优
    • 考察点
    • 加分项
    • 真题汇总

    知识点汇总

    消息队列与数据库

    消息队列

    RabbitMQ

    Erlang开发的开源消息队列,通过Erlang的Actor模型,实现了数据的稳定可靠传输.支持AMQP,XMPP,SMPP等多种协议,因此也比较重量级,由于采用broker代理架构,发送给客户端时,先在中间队列进行排队.RabbitMQ单机吞吐量在万级不算很高

    ActiveMQ

    可部署于代理模式和P2P模式,同样支持多种协议,单机吞吐量在万级.但是不够轻巧,对于队列较多的时候支持不是很好,并且有较低概率丢失消息

    RocketMQ

    阿里开源的消息中间件,单机支持十万级的吞吐量,使用Java开发具有高吞吐量,高可用性的特点,适合在大规模分布式系统中使用

    kafka

    有Scala开发的跨语言高性能分布式消息队列,单机吞吐量在十万级,消息延迟在毫秒级.完全的分布式系统,blocker,producer,consumer都是原生自动支持分布式,依赖ZooKeeper做分布式协调.支持一写多读,可被多个消费者消费.消息皆不会丢失,但可能重复

    数据库

    关系型数据库

    • Oracle
      • 功能强大,缺点贵
    • MySQL
      • 互联网行业中最流行的数据库,业务逻辑简单数据可靠性要求低
    • MariaDB
      • MySQL的分支,由开源社区维护
    • PostgreSQL
      • 类似于Oracle的多进程模型,可支持高并发的应用场景,几乎支持所有SQL标准,适合严格的企业应用场景

    NoSQL(Not Only SQL)

    • Redis
      • 适用于数据变化快,数据大小可预测的场景
    • MongoDB
      • 基于分布式文件存储的数据库
      • 将数据存储为一个文档,数据结构由键值对组成
      • 适用于表结构不明确,数据结构不断发生变化的场景
      • 不适合有事务和复杂查询的场景
    • Hbase
      • 是在hdfs(Hadoop Distributed File System hadoop分布式文件系统)中分布式面向列的数据库,类似于Google的Bigtable
      • 可提供快速随机访问海量结构化数据,在表中由行排序,一个表中有多个列族,每个列族有任意数量的列
      • 依赖于hdfs,可以实现海量数据的可靠存储,适用于数据量大,写多读少,不需要复杂查询的场景
    • Cassandra
      • 高可靠大规模分布式存储系统
      • 支持分布是的结构化K-V存储
      • 以高可用为主要目标
      • 适合写多场景,简单查询,不适合数据统计
    • Pika
      • 提供大容量类Redis的存储服务
      • 兼容Redis的五种数据结构的大部分命令
      • 使用磁盘存储,解决Redis存储成本问题

    NewSQL

    • TiDB
      • 开源分布式关系型数据库
      • 几乎完全兼容MySQL
      • 支持水平弹性扩展,ACID事务,标准SQL,MySQL语法和MySQL协议
      • 具有数据强一致性的高可用性
      • 既适合在线事务处理,也适合在线分析处理
    • OceanBase
      • 蚂蚁金服所有,满足金融级数据可靠性以及数据一致性要求的数据库系统
      • 已商业化不再开源

    数据库范式

    范式级别越高,对数据表要求的越严格

    • 第一范式(最低)
      • 要求表中的字段不可再拆分
    • 第二范式
      • 在满足第一范式的基础上,要求每条记录由主键唯一区分,记录中的所有属性都依赖与主键
    • 第三范式
      • 在满足第二范式的基础上,要求所有属性直接依赖于主键,不允许间接依赖
    • 巴斯-科德范式(一般满足至此即可)
      • 在满足第三范式的基础上,要求联合主键的各字段之间互不依赖
    • 第四范式
    • 第五范式

    知识详解

    Kafka架构

    [外链图片转存失败(img-gu6Ns5tB-1565101632774)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555736863349.png)]

    • Kafka集群有多个server组成,每个server称为一个Broker,为消息代理
    • Kafka中消息是按topic进行划分的,一个topic就是一个queue,实际应用中不同数据可设置为不同topic
    • 一个topic可以有多个consumer,当producer发送数据到topic中时,订阅了该topic的consumer都能接收到消息
    • 为提高并行能力,维护了多个portion分区,每个portion保证id唯一且有序,新消息会储存在队尾,
    • portion持久化时会分段,保证对较小的文件进行写操作,以提高性能
    • 每个topic会被分为多个portion,存于多个broker上,以保证容灾

    Kafka消息生产/生产流程

    [外链图片转存失败(img-iT7kuUlk-1565101632774)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555737083837.png)]

    • 对consumer进行分组管理,以支持消息的一写多读
    • producer有多种方式选择portion,轮循(默认),指定,根据key值得hash选择portion
    • 消息得发送有三种
      • 同步(默认):producer发送消息时,同步获得反馈
      • 异步:producer以batch的方式push消息,可以极大地提高性能,也增加消息丢失风险
      • oneway:只发送消息,不返回结果
    • Kafka确保每个group中只能有一个consumer消费
    • 通过group coordinator管理哪个consumer负责消费哪个portion.默认支持range和轮循分配
    • 在zookeeper中保存了每个topic的每个portion的消费偏移量offset.通过更新offset,以保证每条消息都被消费

    ps.每个consumer线程相当于一个consumer实例,当consumer group中的consumer数量大于portion时,有的consumer会读取不到数据

    数据库事务

    事务特性

    原子性(操作要么全成功,要么失败回滚)、一致性、隔离性(多个事务之间相互隔离)、持久性

    事务并发问题与隔离级别

    脏读:事务处理过程中,读取了另一个事务中未提交的数据

    不可重复读:多次查询,返回不同的数据值(因为中间可能被其他事务更改数据了)

    幻读:第二次查询,结果集不同,记录的增加或删除导致

    [外链图片转存失败(img-ttVPxzM5-1565101632775)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1555737420868.png)]

    事务分类

    • 扁平事务:所有操作都在同一层次(日常使用最多).缺点:不能提交事物的某一部分

    • 带保存点的扁平事务:在事务中插入保存点,失败回滚时,可回滚至任意保存点,而不是回滚整个事务

    • 链事务:可看作上一事务的变种,事务提交时会将上下文隐式传递给下一个事务,事务失败时,回滚至最近的事务

      只能是最近的一个保存点

    • 嵌套事务:由上层事务和子事务组成,类似树形结构.顶层事务负责逻辑处理,子事务负责具体操作.子事务提交后需等待上层事务提交才算完成,若上层事务回滚,则所有子事务回滚

    • 分布式事务:分布式环境中的扁平化事务

      • XA规范:保证强一致性的刚性事务方案
        • 两段式提交 实际中使用多
          • 需要事务协调者保证,事务参与者都完成第一阶段的事务准备阶段.当都准备完成则通知事务参与者进行下一阶段事务.(类似于Java中的countdownlatch和cyclicbarruer)
          • 在一个进程发生故障时,会有较长时间的阻塞
        • 三段式提交
          • 增加PreCommit环节,减少两段式提交中的阻塞时间
      • TCC:满足最终一致性的柔性事务方案
        • 对每个操作都注册确认和补偿操作
        • try阶段:检测业务系统,预留资源
        • confirm阶段:确认提交
        • cancel阶段:业务执行错误时执行回滚,释放预留资源
      • 消息事务:消息一致性方案
        • 将本地操作与消息发送封装在一个事务中,保证本地操作与消息发送要么都成功,要么都失败
        • 下游应用收到收到消息执行对应操作
      • GTS/Fescar(视频中有)

    MySQL

    MySQL
    以下是曾经收集的SQL笔记:
    数据库

    索引

    可大幅增加数据库的查询性能,适合读多写少的场景
    代价:需要额外空间保存索引,插入更新删除时,由于更新索引增加额外的开销

    • 索引类型
      • 唯一索引
        • 索引列中的值唯一,允许出现空值
      • 主键索引
        • 特殊的唯一索引不允许出现空值
      • 普通索引
        • 索引列中的值不唯一,成绩什么的
      • 联合索引
        • 多个列按顺序组成索引,相同列不同顺序为不同索引,最左原则,从左到右匹配
      • 全文索引
        • 只能在char varchar text等类型使用
    • 索引实现
      • B-Tree
        • 最常用,大于或者小于的范围查询
      • R-Tree
        • 用于处理多维数据的数据结构,可对地理数据进行空间索引
      • Hash
        • 效率比B-Tree高,不支持范围查找,排序等功能
      • FullText
        • 适用于全文索引

    MySQL调优

    1. 表结构与索引

      • 分库分表,读写分离
      • 为字段选择合适的数据类型
      • 将字段多的表分拣成多个表,增加中间表
      • 混合范式与反范式,适当冗余
      • 为查询创建必要索引,但避免滥用
      • 尽可能地是以哦那个NOT NULL
    2. SQL语句优化

      • 寻找最需要优化的语句:分析慢查询日志

        • 使用频繁或效率最低的
      • 利用查询工具:explain,profile

        explain:分析语句的执行计划,是否使用索引,使用了哪个索引,扫描了多少记录是否使用了文件排序

        profile:每个语句执行过程中的各分部耗时

      • 避免使用SELECT *, 只取需要的列

        避免查询出不需要使用的字段,避免查询列字段的源信息

      • 尽可能使用prepared statements

        性能更好,防止SQL注入

      • 使用索引扫描来排序

        在有索引的字段上进行排序操作

    3. MySQL参数优化

    4. 硬件及系统配置
      从1到4优化成本增加,优化效果降低

    考察点

    • 了解消息队列,数据库的基本原理和常用队列,数据库的特点

      • 消息队列适用于异步队列,削峰填谷
    • 了解Kafka的架构和消息处理流程

      • 如何通过portion保证并发能力与冗余灾备
      • consumer group如何保证每个consumer不会回去重复的消息
    • 理解数据库事务的ACID特性和隔离级别

    • 掌握常用的MySQL语句和常用函数

      where、order by、join、sum、count

    • 了解MySQL数据库不同引擎多的特点以及不同类型的索引实现

    加分项

    • 了解新特性

      MySQL8.0窗口函数,支持新的查询方式;支持通用表表达式,复杂查询中的嵌入表语句更加清晰

    • 知道数据可表设计原则,有设计经验

      如何对容量进行评估,适当分库分表保证未来服务的可扩展性

    • 有过数据可调优经验

      明明建立了索引语句,但是查询效率还很慢,后来通过explain分析,发现表中有多个索引,MySQL优化器选用了错误的索引导致查询效率偏低,通过SQL语句中使用use index 指定索引来解决

    • 消息队列使用经验,不同场景下的取舍

      日志推送场景,对小概率消息丢失可以容忍可以设置为异步发送消息

      金融类业务,需要设置同步发送消息,并且设置最高的消息可靠性,把request required参数设置为-1

    真题汇总

    • 使用过消息队列吗,在什么场景使用,用来解决什么问题

    • 使用队列是如何保证可靠性

      消息的发送者保证投递到消息队列,消息队列自身的高可用,消费方处理完后修改offset

      可以结合kafka的消息发送同步异步,消息的可靠性配置

    • MQ有可能发生重复消费吗,如何解决

      1.通过对消息处理实现密等,消除消息重复的影响2.使用redis 消息去重,避免重复消息的处理

    • 数据库查询语句很慢,如何优化

      创建索引,减少关联查询,优化SQL查询条件

    • 数据库事务有哪些特性,事务隔离级别有哪几种

    • 如何随SQL语句进行优化

    十二、架构演进与容器技术

    • 系统架构演进
      • 单体架构
      • 微服务架构
        • 分布式体统的CAP原则和BASE理论
      • 云原生服务
        • 云原生的12要素
      • 下一代架构Service Mesh
        • 微服务与Service Mesh的区别与联系
    • 容器
      • Docker
        • Docker原理
      • Kubernetes
        • Kubernetes架构
    • 考察点
    • 加分项
    • 面试技巧
      • 提示

    系统架构演进


    单体架构

    在这里插入图片描述

    一个项目中的多个服务混合部署在一个进程内,服务之间的交互都是通过进程内调用完成的
    优点:快速开发部署服务,服务之间调用的性能最好
    缺点:随着业务增长项目越来越臃肿,服务之间由于jar包引用导致频繁的依赖冲突,服务资源变更困难,一个服务可能被不同业务引用,升级资源需要多个业务方同时升级.业务方可直连业务资源,存在明显的数据安全风险.修改代码后回归困难,架构难以调整等

    以上问题都是由于服务之间的强耦合所导致

    微服务架构

    在这里插入图片描述
    起源是为了解决企业应用问题,特点高内聚低耦合,不同的服务单独开发单独测试单独部署,服务之间通过RPC或HTTP进行远程交互,微服务架构解决了单体架构的耦合问题,但也带来了新的问题.由于不同服务部署在不同进程或主机中,要是用前需要先找到服务,即服务发现
    一般微服务采用两种发现方式

    • RPC方式,通过注册中心完成服务发现.由服务调用端获得服务全部可用节点,再由client进行负载均衡调用服务
    • 通过http调用服务端提供的restful接口,通过nginx反向代理完成负载均衡

    不论哪种方式都从进程内通信变成了远程通信,使得性能下降,可靠性降低

    分布式体统的CAP原则和BASE理论

    Consistency 一致性:所有节点在同一时间的数据完全一致
    Availability 可用性:任意时间总能执行读写任务
    Partition tolerance 分区容差:同出现节点异常时,仍然能提供满足需求的服务
    三者只可能同时满足两个
    只选择CA相当于单机架构
    只选择CP,则允许在极端情况下出现短时的服务不可用,如zookeeper,不适合做服务注册中心
    只选择AP,则允许出现短时间不一致,如eureka

    Basically Available(基本可用),Soft state(软状态),Eventually consistent(最终一致性)
    是对CAP中一致性权衡的结果,即使无法做到强一致性,也可以根据系统的特点采用适当的方法得到最终一致性

    云原生服务

    在这里插入图片描述

    云原生架构由微服务组成,是一种能够快速持续可靠规模化的交付业务服务的模式

    一般为两种,私有云和公有云

    • 容器化的微服务:云原生的主体
    • Devops:对微服务的动态管理
    • 持续交付:云原生的目的

    IaaS提供计算资源
    PaaS平台提供运行环境

    微服务的解耦会导致道德业务拆分成小的服务,每个服务的部署都需要考虑单点问题,需要多机房多节点部署,会造成系统资源的浪费,服务扩容是需重新整理服务依赖的环境
    容器化技术把服务的运行环境进行打包管理,解决了扩缩容时对运行环境的管理问题和服务器的利用率问题
    随着容器技术的逐渐成熟,微服务架构也快速普及

    云原生的12要素

    1. 基准代码:代码由版本管理工具管理,一个应用只有一份基准代码,运行时有多个部署实例
    2. 依赖:在应用中显式的声明依赖
    3. 配置:环境中存储配置,说明配置与代码要分开管理
    4. 后端服务:将依赖的后端服务当作统一资源来对待
    5. 构建,发布,运行:需要严格区分构建,发布,运行三个步骤,并且要按顺序进行
    6. 进程:以一个或多个进程运行,要保证进程的无状态性
    7. 端口绑定:应用启动后,相应的端口可持续提供服务直至应用关闭
    8. 并发:应用进程之间可以并发处理,英雌可以通过对进程方式进行水平扩展
    9. 易处理:应该容易被管理,可以通过优雅停机和快速启动构建最健壮的服务
    10. 开发/生产等价:指在开发生产环境中的应用尽可能一致
    11. 日志:要合理记录应用的运行日志,要把日志当作事件流来对待
    12. 管理进程:把后台管理任务当作一次性进程来运行

    下一代架构Service Mesh

    在这里插入图片描述
    service mesh在微服务的基础上引入了sidecar边车的概念,每个服务都伴生有一个sidecar,服务的交互不再由服务自身完成,服务所有出入的请求都交由sidecar处理,在管理层面对sidecar进行统一管理,由sidecar实现服务发现,负载均衡,流量调度等

    微服务与Service Mesh的区别与联系

    在这里插入图片描述
    微服务要解决的是多个服务之间的耦合问题,如上图绿色竖线,将ServiceA,B,C进行解耦,单独部署单独管理,使得每个服务都要实现服务发现,服务间远程交互,负载均衡,高可用策略,服务熔断等一系列的功能
    service mesh是将与业务逻辑无关的功能进行解耦,如图中红色的线,把与服务交互的功能从服务中剥离出来,统一交由sidecar实现,让服务更聚焦于业务逻辑,提高研发效率.sidecar更专注于服务的交互与治理,追求极致的功能与性能
    因此service mesh并不能称为一项新的技术,而应当是微服务的演进
    由于sidecar是独立进程,所以天然适合为不同语言的服务提供统一的治理能力,因此跨语言治理也是service mesh的一个重要特点
    由于引入了额外的sidecar,service mesh也产生新的性能与可靠性问题,这也是service mesh架构需要解决的问题

    只是让问题转移,方便对问题集中整治和处理,让服务更聚焦于业务研发,不同的功能交给专门的组件处理

    通过架构演进,虽然没有消灭复杂度,但让问题变得透明化,业务无感知,提升服务整体开发效率扩展能力

    容器


    Docker

    微服务架构的基础

    • 作用:
      • 构建,部署,运行服务
      • 服务版本管理
      • 屏蔽环境差异
      • 隔离服务
      • 提高资源利用率
    • 特点:
      • 开源容器技术
      • 基于LXC,高效虚拟化
      • 适合大规模构建
      • 灵活可拓展
      • 管理简单
    • 概念:
      • 镜像(Images):服务代码与运行环境的封装
      • 容器(Container):基于镜像的服务运行状态,可以基于一个镜像运行多个容器
      • 守护进程(Daemon):运行在宿主机上的管理进程,用户通过client与其进行交互
      • 客户端(Client):和守护进程交互的命令行工具
      • 镜像仓库(Repository):

    Docker原理

    在这里插入图片描述
    docker通过对不同运行进程进行隔离实现虚拟化
    docker运用三种方式以实现进程的隔离:

    1. Namespace
      • 进程:docker运用三种方式以实现进程的隔离利用Linux的Namespace隔离进程之间的可见性,不同的服务进程属于不同的Namespace,互相无法感知对方的存在.
      • 网络:docker运用三种方式以实现进程的隔离实现了host,container,null和bridge(默认)四种网络模式.每个容器创建时都会创建一对虚拟网卡,一个在容器中一个在docker0的网桥中,组成了数据的通道.docker0的网桥通过iptables中的配置与宿主机的网卡相连,所有符合条件的请求都会通过iptables转发到docker0,再有网桥分发给相应的容器网卡.
      • 挂载点(文件目录):为防止容器进程修改宿主机的文件目录,docker通过修改进程访问文件目录的根节点结合namespace来隔离不同容器进程可以访问的文件目录
    2. Control Groups:资源限制
    3. UnionFS
      • docker的镜像是分层结构,存在操作系统层,技术环境层,web容器层,服务代码层,层与层相互依赖通过UnionFS把Image的不同分层作为只读目录
      • Container是在Image的只读目录上创建的可读可写的目录
        docker有AUFS, Btrfs, overlay, Devicemapper, zfs等多种不同的存储驱动实现

    Kubernetes(K8s)

    容器集群管理系统,不是PaaS平台

    • 作用:
      • 容器集群管理
      • 自动化部署
      • 自动扩缩容
      • 应用管理
    • 特点:
      • 可移植
      • 可扩展
      • 自动化
    • 概念:
      • Master:管理节点,负责协调集群中所有节点的行为与活动(例,应用的运行,修改,更新等)
      • Node:运行容器,可有多个Pod
      • Pod:Kubernetes可创建部署的基本单位,可运行多个Container
      • Container:为运行中的服务镜像,共享所属Pod的网络存储
      • Service:为Pod添加标签,将其划分为不同的Service
      • Deployment:表示对Kubernetes集群的一次操作(例,创建,更新,滚动升级等)

    Kubernetes架构

    在这里插入图片描述

    • Master
      • api server:用户资源操作的唯一入口
        • 创建应用部署
        • 管理部署状态
        • 认证授权
        • 访问控制
        • api注册和发现
      • controller manager:维护集群状态,包含多个controller(例,node controller,route controller,service controller)
        • 故障检测
        • 自动扩展
        • 滚动更新
      • scheduler:资源调度
    • etcd:保存集群状态
    • kubectl:运行命令的管理工具,与Master中的api server进行交互,通过api server下达指令
    • Node
      • 容器运行时(container runtime):可以不是docker
        • Pod:可看作虚拟服务器,可运行多个Container
      • kubelet:负责人与Master通信,周期性访问api server,进行检查和报告,执行容器的操作,维护容器的生命周期,也负责volume和网络的管理
      • kube-proxy:处理网络代理和容器的负载均衡,通过改变iptables规则,控制容器上的tcp和udp包

    Kubernetes把所有被管理的资源看作对象,使得对资源的管理变成对对象属性的设置,配置文件使用yaml格式
    对象可大致分为四类:

    1. 资源对象
    2. 配置对象
    3. 存储对象
    4. 策略对象

    考察点

    • 表达沟通
    • 分布式架构的理解
      • 系统可用性,扩展性
      • 故障的应对方法
        • 熔断,容灾,流量迁移
      • 架构设计中的解耦
    • 了解系统优化的常用方法
      • 并行,异步,水平扩展,垂直扩展,预处理,缓存,分区
    • 对工作的熟悉程度
      • 自己项目的规模,调用量级
    • 解决问题能力

    加分项

    • 关注业界最新趋势
    • 能提供方案对比选型

    面试技巧

    • 交代背景:
      • STAR法则(情境(situation)、任务(task)、行动(action)、结果(result))
    • 描述架构:架构图或交互流程图
    • 做了什么:突出重点,最重要的突出工作,实现能力和亮点
    • 结果如何:用实力作证
      • 注意量化相关性能数据
    • 如何改进:存在的问题与解决方法,问题的进一步思考,总结反思

    提示

    • 提前思考,提前准备
    • 项目在精不在多
    • 我了解的,就是我的
    • 体现对架构的理解,对设计的理解

    职场成长建议

    1. 有策略的努力

      1-2年,学习新技术,知识的广度,技术的好奇心

      3+,主动思考,学习能力,团队协作,跨团队沟通,项目设计能力

      5+,自己的技术品牌

    2. 打造自己的技术品牌

      工作中责任心,自己的任务一定要做好

      协助同事排查解决技术难题

      做有技术深度或者技术排查案例的分享

      后续的职场人脉建立于此,对今后发展很有帮助

    3. 总结与反思

      某项工作或阶段性任务完成之后,及时总结。有利于发现改进空间,后续准备晋升素材

      1. 获得了哪些收益
      2. 开发中遇到了哪些问题
      3. 哪些问题在设计初期就能避免
      4. 哪些问题要及早解决
      5. 开发中自己哪些地方做的不好,后续如何改建

      完成项目重构

      1. 旧项目的问题
      2. 重构时哪些地方收益最明显
    展开全文
  • 高等数学(下)知识点总结

    万次阅读 多人点赞 2019-03-26 19:12:20
    高等数学(下)知识点总结 首先我们学习了空间解析几何。平面的三种方程适用于不同类型的题目: 类比平面解析几何,不难得出如下的夹角与距离的概念: 研究完平面,我们研究直线。直线也有下面三种方程: ...

    高等数学(下)知识点总结 

    首先我们学习了空间解析几何。平面的三种方程适用于不同类型的题目:

    类比平面解析几何,不难得出如下的夹角与距离的概念:

    研究完平面,我们研究直线。直线也有下面三种方程:

    计算夹角的方法如下:

    用好过直线的平面束,可以解决很多问题:

    研究完直线,我们研究曲线。曲线有如下形式的一般方程:

    曲线也可用参数方程表达:

    我们还有投影的概念:

    研究空间解析几何,一定程度上为多元函数的研究提供了基础,多元函数的最基本概念请同学们牢记:

    随后我们研究了偏导数:

    以及高阶偏导数:

    用好全微分的概念,可以处理很多计算偏导数的题目:

    研究完最简单的偏导数,我们想研究复合函数的偏导数。由于复合方法多种多样,也有如下两种不同的情形:

    隐函数定理压轴登场!一个方程的情形,计算偏导数的公式如下:

    方程组联立的情形下,我们引入了雅可比行列式的概念,方法如下。乍一看公式似乎很复杂,实际就是解一个线性方程组~

    除了在坐标轴方向有偏导数,我们在任意方向都可以定义方向导数。自然要用到梯度的概念:

    多元函数微分学反过来对第一章的空间解析几何提供了方法:

    在没有限制条件的情况下,我们可以借助偏导数求出多元函数的极值:

    接触过中学数学竞赛的同学会被中学数学竞赛那细微的放缩以及“先猜后证”弄得晕头转向,而这里的拉格朗日乘子法,让你秒杀多元条件极值问题!

    上学期同学们学习了定积分、反常积分,不过有的特定的反常积分是无法用传统方法解出来的。这就要借助我们的重积分了。类比定积分,二重积分有以下两个性质:

    如何计算重积分,可以说是高数中的关键部分。一般来说,我们把积分区域划分成如下两种区域,再进行求解,实际上,我们还是在做定积分。必要的时候,还要交换积分次序。

    三重积分最基本的计算方法有两种,我们的思想就是把三重积分转化为二重积分和定积分,这两种方法分别叫“先一后二”和“先二后一”:

    当然,有时候利用对称性,可以大大简化问题:

    我们还介绍了柱坐标系、球坐标系,其体积元可以借助雅可比行列式计算出。这两种坐标系常常能简化问题,就如同二重积分中的极坐标一样。

    重积分后,我们有线、面积分:

    曲线积分的一般方法如下:

    曲面积分的一般方法如下:

    接下来是本章最重要的公式之一——格林公式及其推论:

    同为最重要的公式之一——高斯公式:

    学期的最后,我们学习了级数的相关理论,审敛法需牢记~

    我们又讲了两种重要的函数项级数——幂级数和傅里叶级数。幂级数其实同学们在学泰勒公式的时候已经接触到了~而傅里叶级数,以三角级数拟合一般的周期函数,它的提出是一种非常伟大的想法。傅里叶级数的公式稍微复杂,请同学们记住有关公式和结论,不要弄混淆了~

    至此,高数(下)的内容就回顾完了。

    转自:https://www.sohu.com/a/239378031_185748

    展开全文
  • Java知识点全面汇总

    万次阅读 多人点赞 2018-07-29 20:50:12
     相关概念 面向对象的三个特征 封装,继承,多态,这个应该是人人皆知,有时候也会加上抽象。 多态的好处 ...允许不同类对象对同一消息做出响应,即同一消息可以根据发送对象的不同而采用多种不同的行为方式...

    

    相关概念

    面向对象的三个特征

    封装,继承,多态,这个应该是人人皆知,有时候也会加上抽象。

    多态的好处

    允许不同类对象对同一消息做出响应,即同一消息可以根据发送对象的不同而采用多种不同的行为方式(发送消息就是函数调用)。主要有以下优点:

    1. 可替换性:多态对已存在代码具有可替换性

    2. 可扩充性:增加新的子类不影响已经存在的类结构

    3. 接口性:多态是超类通过方法签名,向子类提供一个公共接口,由子类来完善或者重写它来实现的。

    4. 灵活性

    5. 简化性

    代码中如何实现多态

    实现多态主要有以下三种方式
    1. 接口实现 
    2. 继承父类重写方法 
    3. 同一类中进行方法重载

    虚拟机是如何实现多态的

    动态绑定技术(dynamic binding),执行期间判断所引用对象的实际类型,根据实际类型调用对应的方法。

    接口的意义

    接口的意义用三个词就可以概括:规范,扩展,回调。

    抽象类的意义

    抽象类的意义可以用三句话来概括:

    1. 为其他子类提供一个公共的类型

    2. 封装子类中重复定义的内容

    3. 定义抽象方法,子类虽然有不同的实现,但是定义时一致的

    接口和抽象类的区别https://blog.csdn.net/weixin_37766296/article/details/80316284


    父类的静态方法能否被子类重写

    不能。重写只适用于实例方法,不能用于静态方法,而子类当中含有和父类相同签名的静态方法,我们一般称之为隐藏

    什么是不可变对象

    不可变对象指对象一旦被创建,状态就不能再改变。任何修改都会创建一个新的对象,如 String、Integer及其它包装类

    静态变量和实例变量的区别?(使用范围不一样)

    静态变量存储在方法区,属于类所有。实例变量存储在堆当中,其引用存在当前线程栈。

    能否创建一个包含可变对象的不可变对象?

    当然可以创建一个包含可变对象的不可变对象的,你只需要谨慎一点,不要共享可变对象的引用就可以了,如果需要变化时,就返回原对象的一个拷贝。最常见的例子就是对象中包含一个日期对象的引用。

    java 创建对象的几种方式

    1. 采用new

    2. 通过反射

    3. 采用clone

    4. 通过序列化机制

    前2者都需要显式地调用构造方法。造成耦合性最高的恰好是第一种,因此你发现无论什么框架,只要涉及到解耦必先减少new的使用。

    switch中能否使用string做参数

    在idk 1.7之前,switch只能支持byte, short, char, int或者其对应的封装类以及Enum类型。从idk 1.7之后switch开始支持String。

    switch能否作用在byte, long上?

    可以用在byte上,但是不能用在long上。

    String s1=”ab”, String s2=”a”+”b”, String s3=”a”, String s4=”b”, s5=s3+s4请问s5==s2返回什么?

    返回false。在编译过程中,编译器会将s2直接优化为”ab”,会将其放置在常量池当中,s5则是被创建在堆区,相当于s5=new String(“ab”);

    你对String对象的intern()熟悉么?

    intern()方法会首先从常量池中查找是否存在该常量值,如果常量池中不存在则现在常量池中创建,如果已经存在则直接返回。
    比如 
    String s1=”aa”; 
    String s2=s1.intern(); 
    System.out.print(s1==s2);//返回true

    Object中有哪些公共方法?

    1. equals()

    2. clone()

    3. getClass()

    4. notify(),notifyAll(),wait()

    5. toString

       

    java当中的四种引用

    强引用,软引用,弱引用,虚引用。不同的引用类型主要体现在GC上:

    1. 强引用:如果一个对象具有强引用,它就不会被垃圾回收器回收。即使当前内存空间不足,JVM也不会回收它,而是抛出 OutOfMemoryError 错误,使程序异常终止。如果想中断强引用和某个对象之间的关联,可以显式地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象。

    2. 软引用:在使用软引用时,如果内存的空间足够,软引用就能继续被使用,而不会被垃圾回收器回收,只有在内存不足时,软引用才会被垃圾回收器回收。

    3. 弱引用:具有弱引用的对象拥有的生命周期更短暂。因为当 JVM 进行垃圾回收,一旦发现弱引用对象,无论当前内存空间是否充足,都会将弱引用回收。不过由于垃圾回收器是一个优先级较低的线程,所以并不一定能迅速发现弱引用对象。

    4. 虚引用:顾名思义,就是形同虚设,如果一个对象仅持有虚引用,那么它相当于没有引用,在任何时候都可能被垃圾回收器回收。

     

    更多了解参见深入对象引用:

    http://blog.csdn.net/dd864140130/article/details/49885811

    WeakReference与SoftReference的区别?

    这点在四种引用类型中已经做了解释,这里简单说明一下即可: 
    虽然 WeakReference 与 SoftReference 都有利于提高 GC 和 内存的效率,但是 WeakReference ,一旦失去最后一个强引用,就会被 GC 回收,而软引用虽然不能阻止被回收,但是可以延迟到 JVM 内存不足的时候。

    为什么要有不同的引用类型

    不像C语言,我们可以控制内存的申请和释放,在Java中有时候我们需要适当的控制对象被回收的时机,因此就诞生了不同的引用类型,可以说不同的引用类型实则是对GC回收时机不可控的妥协。有以下几个使用场景可以充分的说明:

    1. 利用软引用和弱引用解决OOM问题:用一个HashMap来保存图片的路径和相应图片对象关联的软引用之间的映射关系,在内存不足时,JVM会自动回收这些缓存图片对象所占用的空间,从而有效地避免了OOM的问题.

    2. 通过软引用实现Java对象的高速缓存:比如我们创建了一Person的类,如果每次需要查询一个人的信息,哪怕是几秒中之前刚刚查询过的,都要重新构建一个实例,这将引起大量Person对象的消耗,并且由于这些对象的生命周期相对较短,会引起多次GC影响性能。此时,通过软引用和 HashMap 的结合可以构建高速缓存,提供性能。

    java中==和eqauls()的区别,equals()和`hashcode的区别

    ==是运算符,用于比较两个变量是否相等,而equals是Object类的方法,用于比较两个对象是否相等。默认Object类的equals方法是比较两个对象的地址,此时和==的结果一样。换句话说:基本类型比较用==,比较的是他们的值。默认下,对象用==比较时,比较的是内存地址,如果需要比较对象内容,需要重写equal方法。

    equals()hashcode()的联系

    hashCode()是Object类的一个方法,返回一个哈希值。如果两个对象根据equal()方法比较相等,那么调用这两个对象中任意一个对象的hashCode()方法必须产生相同的哈希值。
    如果两个对象根据eqaul()方法比较不相等,那么产生的哈希值不一定相等(碰撞的情况下还是会相等的。)

    a.hashCode()有什么用?与a.equals(b)有什么关系

    hashCode() 方法是相应对象整型的 hash 值。它常用于基于 hash 的集合类,如 Hashtable、HashMap、LinkedHashMap等等。它与 equals() 方法关系特别紧密。根据 Java 规范,使用 equal() 方法来判断两个相等的对象,必须具有相同的 hashcode。

    将对象放入到集合中时,首先判断要放入对象的hashcode是否已经在集合中存在,不存在则直接放入集合。如果hashcode相等,然后通过equal()方法判断要放入对象与集合中的任意对象是否相等:如果equal()判断不相等,直接将该元素放入集合中,否则不放入。

    有没有可能两个不相等的对象有相同的hashcode

    有可能,两个不相等的对象可能会有相同的 hashcode 值,这就是为什么在 hashmap 中会有冲突。如果两个对象相等,必须有相同的hashcode 值,反之不成立。

    可以在hashcode中使用随机数字吗?

    不行,因为同一对象的 hashcode 值必须是相同的

    a==b与a.equals(b)有什么区别

    如果a 和b 都是对象,则 a==b 是比较两个对象的引用,只有当 a 和 b 指向的是堆中的同一个对象才会返回 true,而 a.equals(b) 是进行逻辑比较,所以通常需要重写该方法来提供逻辑一致性的比较。例如,String 类重写 equals() 方法,所以可以用于两个不同对象,但是包含的字母相同的比较。

    3*0.1==0.3返回值是什么

    false,因为有些浮点数不能完全精确的表示出来。

    a=a+b与a+=b有什么区别吗?

    +=操作符会进行隐式自动类型转换,此处a+=b隐式的将加操作的结果类型强制转换为持有结果的类型,而a=a+b则不会自动进行类型转换。如:
    byte a = 127; 
    byte b = 127; 
    b = a + b; // error : cannot convert from int to byte 
    b += a; // ok 
    (译者注:这个地方应该表述的有误,其实无论 a+b 的值为多少,编译器都会报错,因为 a+b 操作会将 a、b 提升为 int 类型,所以将 int 类型赋值给 byte 就会编译出错)

    short s1= 1; s1 = s1 + 1; 该段代码是否有错,有的话怎么改?

    有错误,short类型在进行运算时会自动提升为int类型,也就是说s1+1的运算结果是int类型。

    short s1= 1; s1 += 1; 该段代码是否有错,有的话怎么改?

    +=操作符会自动对右边的表达式结果强转匹配左边的数据类型,所以没错。

    & 和 &&的区别

    首先记住&是位操作,而&&是逻辑运算符。另外需要记住逻辑运算符具有短路特性,而&不具备短路特性。

    public class Test{
       static String name;
    
       public static void main(String[] args){
           if(name!=null&userName.equals("")){
               System.out.println("ok");
           }else{
               System.out.println("erro");
           }
       }
    }

     

    以上代码将会抛出空指针异常。

    一个java文件内部可以有类?(非内部类)

    能有一个public公共类,但是可以有多个default修饰的类。

     

     

    如何正确的退出多层嵌套循环?

    使用标号和break;

    通过在外层循环中添加标识符

     

     

     

    内部类的作用

    内部类可以有多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立.在单个外围类当中,可以让多个内部类以不同的方式实现同一接口,或者继承同一个类.创建内部类对象的时刻不依赖于外部类对象的创建。内部类并没有令人疑惑的”is-a”管系,它就像是一个独立的实体。

    内部类提供了更好的封装,除了该外围类,其他类都不能访问。

    final, finalize和finally的不同之处

    final 是一个修饰符,可以修饰变量、方法和类。如果 final 修饰变量,意味着该变量的值在初始化后不能被改变。finalize 方法是在对象被回收之前调用的方法,给对象自己最后一个复活的机会,但是什么时候调用 finalize 没有保证。finally 是一个关键字,与 try 和 catch 一起用于异常的处理。finally 块一定会被执行,无论在 try 块中是否有发生异常。

    clone()是哪个类的方法?

    java.lang.Cloneable 是一个标示性接口,不包含任何方法,clone 方法在 object 类中定义。并且需要知道 clone() 方法是一个本地方法,这意味着它是由 c 或 c++ 或 其他本地语言实现的。

    深拷贝和浅拷贝的区别是什么?

    浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象。

    深拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深拷贝把要复制的对象所引用的对象都复制了一遍。

    static都有哪些用法?

    几乎所有的人都知道static关键字这两个基本的用法:静态变量和静态方法。也就是被static所修饰的变量/方法都属于类的静态资源,类实例所共享。

    除了静态变量和静态方法之外,static也用于静态块,多用于初始化操作

    public calss PreCache{
       static{
           //执行相关操作
       }
    }

     

    此外static也多用于修饰内部类,此时称之为静态内部类。

    最后一种用法就是静态导包,即import static.import static是在JDK 1.5之后引入的新特性,可以用来指定导入某个类中的静态资源,并且不需要使用类名。资源名,可以直接使用资源名,比如:

    import static java.lang.Math.*;
    
    public class Test{
    
       public static void main(String[] args){
           //System.out.println(Math.sin(20));传统做法
           System.out.println(sin(20));
       }
    }

     

    final有哪些用法

    final也是很多面试喜欢问的地方,能回答下以下三点就不错了:
    1.被final修饰的类不可以被继承 
    2.被final修饰的方法不可以被重写 
    3.被final修饰的变量不可以被改变。如果修饰引用,那么表示引用不可变,引用指向的内容可变。
    4.被final修饰的方法,JVM会尝试将其内联,以提高运行效率 
    5.被final修饰的常量,在编译阶段会存入常量池中。

    回答出编译器对final域要遵守的两个重排序规则更好:
    1.在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序。
    2.初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能重排序。

    数据类型相关

    java中int char,long各占多少字节?

    类型 位数 字节数
    short 2 16
    int 4 32
    long 8

    64

    char 2 16
    float 4 32
    double 8 64
         


    64位的JVM当中,int的长度是多少?

    Java 中,int 类型变量的长度是一个固定值,与平台无关,都是 32 位。意思就是说,在 32 位 和 64 位 的Java 虚拟机中,int 类型的长度是相同的。

    int和Integer的区别

    Integer是int的包装类型,在拆箱和装箱中,二者自动转换。int是基本类型,直接存数值,而integer是对象,用一个引用指向这个对象。

    int 和Integer谁占用的内存更多?

    Integer 对象会占用更多的内存。Integer是一个对象,需要存储对象的元数据。但是 int 是一个原始类型的数据,所以占用的空间更少

    String, StringBuffer和StringBuilder区别

    String是字符串常量,final修饰:StringBuffer字符串变量(线程安全);
    StringBuilder 字符串变量(线程不安全)。

    String和StringBuffer

    String和StringBuffer主要区别是性能:String是不可变对象,每次对String类型进行操作都等同于产生了一个新的String对象,然后指向新的String对象。所以尽量不在对String进行大量的拼接操作,否则会产生很多临时对象,导致GC开始工作,影响系统性能。

    StringBuffer是对对象本身操作,而不是产生新的对象,因此在有大量拼接的情况下,我们建议使用StringBuffer。

    但是需要注意现在JVM会对String拼接做一定的优化:
    String s=“This is only ”+”simple”+”test”会被虚拟机直接优化成String s=“This is only simple test”,此时就不存在拼接过程

    StringBuffer和StringBuilder

    StringBuffer是线程安全的可变字符串,其内部实现是可变数组。StringBuilder是jdk 1.5新增的,其功能和StringBuffer类似,但是非线程安全。因此,在没有多线程问题的前提下,使用StringBuilder会取得更好的性能。

    什么是编译器常量?使用它有什么风险?

    公共静态不可变(public static final )变量也就是我们所说的编译期常量,这里的 public 可选的。实际上这些变量在编译时会被替换掉,因为编译器知道这些变量的值,并且知道这些变量在运行时不能改变。这种方式存在的一个问题是你使用了一个内部的或第三方库中的公有编译时常量,但是这个值后面被其他人改变了,但是你的客户端仍然在使用老的值,甚至你已经部署了一个新的jar。为了避免这种情况,当你在更新依赖 JAR 文件时,确保重新编译你的程序

    java当中使用什么类型表示价格比较好?

    如果不是特别关心内存和性能的话,使用BigDecimal,否则使用预定义精度的 double 类型。

    如何将byte转为String

    可以使用 String 接收 byte[] 参数的构造器来进行转换,需要注意的点是要使用的正确的编码,否则会使用平台默认编码,这个编码可能跟原来的编码相同,也可能不同。

    可以将int强转为byte类型么?会产生什么问题?

    我们可以做强制转换,但是Java中int是32位的而byte是8 位的,所以,如果强制转化int类型的高24位将会被丢弃,byte 类型的范围是从-128到128

    关于垃圾回收

    你知道哪些垃圾回收算法?

    垃圾回收从理论上非常容易理解,具体的方法有以下几种: 
    1. 标记-清除 
    2. 标记-复制 
    3. 标记-整理 
    4. 分代回收
     
    更详细的内容参见深入理解垃圾回收算法:点击打开链接

    如何判断一个对象是否应该被回收

    这就是所谓的对象存活性判断,常用的方法有两种:1.引用计数法; 2.对象可达性分析。由于引用计数法存在互相引用导致无法进行GC的问题,所以目前JVM虚拟机多使用对象可达性分析算法。

    简单的解释一下垃圾回收

    Java 垃圾回收机制最基本的做法是分代回收。内存中的区域被划分成不同的世代,对象根据其存活的时间被保存在对应世代的区域中。一般的实现是划分成3个世代:年轻、年老和永久(新生,老年,持久)。内存的分配是发生在年轻世代中的。当一个对象存活时间足够长的时候,它就会被复制到年老世代中。对于不同的世代可以使用不同的垃圾回收算法。进行世代划分的出发点是对应用中对象存活时间进行研究之后得出的统计规律。一般来说,一个应用中的大部分对象的存活时间都很短。比如局部变量的存活时间就只在方法的执行过程中。基于这一点,对于年轻世代的垃圾回收算法就可以很有针对性。

    调用System.gc()会发生什么?

    通知GC开始工作,但是GC真正开始的时间不确定。


    进程,线程相关

    说说进程,线程,协程之间的区别

    简而言之,进程是程序运行和资源分配的基本单位,一个程序至少有一个进程,一个进程至少有一个线程。进程在执行过程中拥有独立的内存单元,而多个线程共享内存资源减少切换次数从而效率更高。线程是进程的一个实体,是cpu调度和分派的基本单位,是比程序更小的能独立运行的基本单位。同一进程中的多个线程之间可以并发执行。

    你了解守护线程吗?它和非守护线程有什么区别

    程序运行完毕,jvm会等待非守护线程完成后关闭,但是jvm不会等待守护线程。守护线程最典型的例子就是GC线程。

    什么是多线程上下文切换

    多线程的上下文切换是指CPU控制权一个已经正在运行的线程切换到另外一个就绪并等待获取CPU执行权的线程的过程。

    创建两种线程的方式?他们有什么区别?

    通过实现java.lang.Runnable或者通过扩展java.lang.Thread类。相比扩展Thread,实现Runnable接口可能更优.原因有二:

    1. Java不支持多继承。因此扩展Thread类就代表这个子类不能扩展其他类。而实现Runnable接口的类还可能扩展另一个类。

    2. 类可能只要求可执行即可,因此继承整个Thread类的开销过大

    Thread类中的start()和run()方法有什么区别?

    start()方法被用来启动新创建的线程,而且start()内部调用了run()方法,这和直接调用run()方法的效果不一样。当你调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程。

    怎么检测一个线程是否持有对象监视器

    Thread类提供了一个holdsLock(Object obj)方法,当且仅当对象obj的监视器被某条线程持有的时候才会返回true,注意这是一个static方法,这意味着”某条线程”指的是当前线程。

    Runnable和Callable的区别

    Runnable接口中的run()方法的返回值是void,它做的事情只是纯粹地去执行run()方法中的代码而已;Callable接口中的call()方法是有返回值的,是一个泛型,和Future、FutureTask配合可以用来获取异步执行的结果。 
    这其实是很有用的一个特性,因为多线程相比单线程更难、更复杂的一个重要原因就是因为多线程充满着未知性,某条线程是否执行了?某条线程执行了多久?某条线程执行的时候我们期望的数据是否已经赋值完毕?无法得知,我们能做的只是等待这条多线程的任务执行完毕而已。而Callable+Future/FutureTask却可以方便获取多线程运行的结果可以在等待时间太长没获取到需要的数据的情况下取消该线程的任务。

    什么导致线程阻塞

    阻塞指的是暂停一个线程的执行以等待某个条件发生如某资源就绪),学过操作系统的同学对它一定已经很熟悉了。Java 提供了大量方法来支持阻塞,下面让我们逐一分析。

    方法 说明
    sleep() sleep() 允许 指定以毫秒为单位的一段时间作为参数,它使得线程在指定的时间内进入阻塞状态,不能得到CPU 时间,指定的时间一过,线程重新进入可执行状态。 典型地,sleep() 被用在等待某个资源就绪的情形:测试发现条件不满足后,让线程阻塞一段时间后重新测试,直到条件满足为止
    suspend() 和 resume() 两个方法配套使用,suspend()使得线程进入阻塞状态,并且不会自动恢复,必须其对应的resume() 被调用,才能使得线程重新进入可执行状态。典型地,suspend() 和 resume() 被用在等待另一个线程产生的结果的情形:测试发现结果还没有产生后,让线程阻塞,另一个线程产生了结果后,调用 resume() 使其恢复
    yield() yield() 使当前线程放弃当前已经分得的CPU 时间,但不使当前线程阻塞,即线程仍处于可执行状态,随时可能再次分得 CPU 时间。调用 yield() 的效果等价于调度程序认为该线程已执行了足够的时间从而转到另一个线程
    wait() 和 notify() 两个方法配套使用,wait() 使得线程进入阻塞状态,它有两种形式一种允许 指定以毫秒为单位的一段时间作为参数,另一种没有参数,前者当对应的 notify() 被调用或者超出指定时间时线程重新进入可执行状态,后者则必须对应的 notify() 被调用


    wait(),notify()和suspend(),resume()之间的区别

    (参考博文:点击打开链接

    初看起来它们与 suspend() 和 resume() 方法对没有什么分别,但是事实上它们是截然不同的。区别的核心在于,前面叙述的所有方法,阻塞时都不会释放占用的锁(如果占用了的话),而这一对方法则相反。上述的核心区别导致了一系列的细节上的区别。

    首先,前面叙述的所有方法都隶属于 Thread 类,但是这一对却直接隶属于 Object 类,也就是说,所有对象都拥有这一对方法。初看起来这十分不可思议,但是实际上却是很自然的,因为这一对方法阻塞时要释放占用的锁,而锁是任何对象都具有的,调用任意对象的 wait() 方法导致线程阻塞,并且该对象上的锁被释放。而调用 任意对象的notify()方法则导致从调用该对象的 wait() 方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。

    其次,前面叙述的所有方法都可在任何位置调用,但是这一对方法却必须在 synchronized 方法或块中调用,理由也很简单,只有在synchronized 方法或块中当前线程才占有锁,才有锁可以释放。同样的道理,调用这一对方法的对象上的锁必须为当前线程所拥有,这样才有锁可以释放。因此,这一对方法调用必须放置在这样的 synchronized 方法或块中,该方法或块的上锁对象就是调用这一对方法的对象。若不满足这一条件,则程序虽然仍能编译,但在运行时会出现IllegalMonitorStateException 异常。

    wait() 和 notify() 方法的上述特性决定了它们经常和synchronized关键字一起使用,将它们和操作系统进程间通信机制作一个比较就会发现它们的相似性:synchronized方法或块提供了类似于操作系统原语的功能,它们的执行不会受到多线程机制的干扰,而这一对方法则相当于 block 和wakeup 原语(这一对方法均声明为 synchronized)。它们的结合使得我们可以实现操作系统上一系列精妙的进程间通信的算法(如信号量算法),并用于解决各种复杂的线程间通信问题。

    关于 wait() 和 notify() 方法最后再说明两点: 
    第一:调用 notify() 方法导致解除阻塞的线程是从因调用该对象的 wait() 方法而阻塞的线程中随机选取的,我们无法预料哪一个线程将会被选择,所以编程时要特别小心,避免因这种不确定性而产生问题。

    第二:除了 notify(),还有一个方法 notifyAll() 也可起到类似作用,唯一的区别在于,调用 notifyAll() 方法将把因调用该对象的 wait() 方法而阻塞的所有线程一次性全部解除阻塞。当然,只有获得锁的那一个线程才能进入可执行状态。

    谈到阻塞,就不能不谈一谈死锁,略一分析就能发现,suspend() 方法和不指定超时期限的 wait() 方法的调用都可能产生死锁。遗憾的是,Java 并不在语言级别上支持死锁的避免,我们在编程中必须小心地避免死锁。

    以上我们对 Java 中实现线程阻塞的各种方法作了一番分析,我们重点分析了 wait() 和 notify() 方法,因为它们的功能最强大,使用也最灵活,但是这也导致了它们的效率较低,较容易出错。实际使用中我们应该灵活使用各种方法,以便更好地达到我们的目的。

    产生死锁的条件(互请不循环)

    1.互斥条件:一个资源每次只能被一个进程使用。 
    2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。 
    3.不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。 
    4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

    为什么wait()方法和notify()/notifyAll()方法要在同步块中被调用

    这是JDK强制的,wait()方法和notify()/notifyAll()方法在调用前都必须先获得对象的锁

    wait()方法和notify()/notifyAll()方法在放弃对象监视器时有什么区别

    wait()方法和notify()/notifyAll()方法在放弃对象监视器的时候的区别在于:wait()方法立即释放对象监视器,notify()/notifyAll()方法则会等待线程剩余代码执行完毕才会放弃对象监视器。

    wait()与sleep()的区别

    关于这两者已经在上面进行详细的说明,这里就做个概括好了:

    • sleep()来自Thread类,和wait()来自Object类。调用sleep()方法的过程中,线程不会释放对象锁。而 调用 wait 方法线程会释放对象锁

    • sleep()睡眠后不出让系统资源,wait让其他线程可以占用CPU

    • sleep(milliseconds)需要指定一个睡眠时间,时间一到会自动唤醒.而wait()可需要配合notify()或者notifyAll()使用

       

       

    为什么wait, nofity和nofityAll这些方法不放在Thread类当中

    一个很明显的原因是JAVA提供的锁是对象级的而不是线程级的,每个对象都有锁,通过线程获得。如果线程需要等待某些锁那么调用对象中的wait()方法就有意义了。如果wait()方法定义在Thread类中,线程正在等待的是哪个锁就不明显了。简单的说,由于wait,notify和notifyAll都是锁级别的操作,所以把他们定义在Object类中因为锁属于对象。

    怎么唤醒一个阻塞的线程

    如果线程是因为调用了wait()、sleep()或者join()方法而导致的阻塞,可以中断线程,并且通过抛出InterruptedException来唤醒它;如果线程遇到了IO阻塞,无能为力,因为IO是操作系统实现的,Java代码并没有办法直接接触到操作系统。

    什么是多线程的上下文切换

    多线程的上下文切换是指CPU控制权由一个已经正在运行的线程切换到另外一个就绪并等待获取CPU执行权的线程的过程。

    synchronized和ReentrantLock的区别

    https://blog.csdn.net/qq838642798/article/details/65441415

    synchronized是和if、else、for、while一样的关键字,ReentrantLock是类,这是二者的本质区别。既然ReentrantLock是类,那么它就提供了比synchronized更多更灵活的特性,可以被继承、可以有方法、可以有各种各样的类变量,ReentrantLock比synchronized的扩展性体现在几点上: 
    (1)ReentrantLock可以对获取锁的等待时间进行设置,这样就避免了死锁 
    (2)ReentrantLock可以获取各种锁的信息 
    (3)ReentrantLock可以灵活地实现多路通知 
    另外,二者的锁机制其实也是不一样的:ReentrantLock底层调用的是Unsafe的park方法加锁,synchronized操作的应该是对象头中mark word。

    FutureTask是什么

    这个其实前面有提到过,FutureTask表示一个异步运算的任务。FutureTask里面可以传入一个Callable的具体实现类,可以对这个异步运算的任务的结果进行等待获取、判断是否已经完成、取消任务等操作。当然,由于FutureTask也是Runnable接口的实现类,所以FutureTask也可以放入线程池中。

    一个线程如果出现了运行时异常怎么办?

    如果这个异常没有被捕获的话,这个线程就停止执行了。另外重要的一点是:如果这个线程持有某个某个对象的监视器,那么这个对象监视器会被立即释放。

    Java当中有哪几种锁

    1. 自旋锁: 自旋锁在JDK1.6之后就默认开启了。基于之前的观察,共享数据的锁定状态只会持续很短的时间,为了这一小段时间而去挂起和恢复线程有点浪费,所以这里就做了一个处理,让后面请求锁的那个线程在稍等一会,但是不放弃处理器的执行时间,看看持有锁的线程能否快速释放。为了让线程等待,所以需要让线程执行一个忙循环也就是自旋操作。在jdk6之后,引入了自适应的自旋锁,也就是等待的时间不再固定了,而是由上一次在同一个锁上的自旋时间及锁的拥有者状态来决定。

    2. 偏向锁: 在JDK1.之后引入的一项锁优化,目的是消除数据在无竞争情况下的同步原语。进一步提升程序的运行性能。 偏向锁就是偏心的偏,意思是这个锁会偏向第一个获得他的线程,如果接下来的执行过程中,改锁没有被其他线程获取,则持有偏向锁的线程将永远不需要再进行同步。偏向锁可以提高带有同步但无竞争的程序性能,也就是说他并不一定总是对程序运行有利,如果程序中大多数的锁都是被多个不同的线程访问,那偏向模式就是多余的,在具体问题具体分析的前提下,可以考虑是否使用偏向锁。

    3. 轻量级锁: 为了减少获得锁和释放锁所带来的性能消耗,引入了“偏向锁”和“轻量级锁”,所以在Java SE1.6里锁一共有四种状态,无锁状态,偏向锁状态,轻量级锁状态和重量级锁状态,它会随着竞争情况逐渐升级。锁可以升级但不能降级,意味着偏向锁升级成轻量级锁后不能降级成偏向锁。

    如何在两个线程间共享数据

    通过在线程之间共享对象就可以了,然后通过wait/notify/notifyAll、await/signal/signalAll进行唤起和等待,比方说阻塞队列BlockingQueue就是为线程之间共享数据而设计的。

    如何正确的使用wait()?使用if还是while?

    wait() 方法应该在循环调用,因为当线程获取到 CPU 开始执行的时候,其他条件可能还没有满足,所以在处理前,循环检测条件是否满足会更好。下面是一段标准的使用 wait 和 notify 方法的代码:

    synchronized (obj) {
       while (condition does not hold)
         obj.wait(); // (Releases lock, and reacquires on wakeup)
         ... // Perform action appropriate to condition
    }

     

    什么是线程局部变量ThreadLocal

    线程局部变量是局限于线程内部的变量,属于线程自身所有,不在多个线程间共享。Java提供ThreadLocal类来支持线程局部变量,是一种实现线程安全的方式。但是在管理环境下(如 web 服务器)使用线程局部变量的时候要特别小心,在这种情况下,工作线程的生命周期比任何应用变量的生命周期都要长。任何线程局部变量一旦在工作完成后没有释放,Java 应用就存在内存泄露的风险。

    ThreadLoal的作用是什么?

    简单说ThreadLocal就是一种以空间换时间的做法在每个Thread里面维护了一个ThreadLocal.ThreadLocalMap把数据进行隔离,数据不共享,自然就没有线程安全方面的问题了。

    生产者消费者模型的作用是什么?

    (1)通过平衡生产者的生产能力和消费者的消费能力来提升整个系统的运行效率,这是生产者消费者模型最重要的作用。
    (2)解耦,这是生产者消费者模型附带的作用,解耦意味着生产者和消费者之间的联系少,联系越少越可以独自发展而不需要收到相互的制约。

    写一个生产者-消费者队列

    可以通过阻塞队列实现,也可以通过wait-notify来实现。

    使用阻塞队列来实现

    //消费者
    public class Producer implements Runnable{
       private final BlockingQueue<Integer> queue;
    
       public Producer(BlockingQueue q){
           this.queue=q;
       }
    
       @Override
       public void run() {
           try {
               while (true){
                   Thread.sleep(1000);//模拟耗时
                   queue.put(produce());
               }
           }catch (InterruptedException e){
    
           }
       }
    
       private int produce() {
           int n=new Random().nextInt(10000);
           System.out.println("Thread:" + Thread.currentThread().getId() + " produce:" + n);
           return n;
       }
    }
    //消费者
    public class Consumer implements Runnable {
       private final BlockingQueue<Integer> queue;
    
       public Consumer(BlockingQueue q){
           this.queue=q;
       }
    
       @Override
       public void run() {
           while (true){
               try {
                   Thread.sleep(2000);//模拟耗时
                   consume(queue.take());
               }catch (InterruptedException e){
    
               }
    
           }
       }
    
       private void consume(Integer n) {
           System.out.println("Thread:" + Thread.currentThread().getId() + " consume:" + n);
    
       }
    }
    //测试
    public class Main {
    
       public static void main(String[] args) {
           BlockingQueue<Integer> queue=new ArrayBlockingQueue<Integer>(100);
           Producer p=new Producer(queue);
           Consumer c1=new Consumer(queue);
           Consumer c2=new Consumer(queue);
    
           new Thread(p).start();
           new Thread(c1).start();
           new Thread(c2).start();
       }
    }

     

    使用wait-notify来实现

    该种方式应该最经典,这里就不做说明了。

    如果你提交任务时,线程池队列已满,这时会发生什么

    如果你使用的LinkedBlockingQueue,也就是无界队列的话,没关系,继续添加任务到阻塞队列中等待执行,因为LinkedBlockingQueue可以近乎认为是一个无穷大的队列,可以无限存放任务;如果你使用的是有界队列比方说ArrayBlockingQueue的话,任务首先会被添加到ArrayBlockingQueue中,ArrayBlockingQueue满了,则会使用拒绝策略RejectedExecutionHandler处理满了的任务,默认是AbortPolicy。

    为什么要使用线程池

    避免频繁地创建和销毁线程,达到线程对象的重用。另外,使用线程池还可以根据项目灵活地控制并发的数目。

    java中用到的线程调度算法是什么

    抢占式。一个线程用完CPU之后,操作系统会根据线程优先级、线程饥饿情况等数据算出一个总的优先级并分配下一个时间片给某个线程执行。

    Thread.sleep(0)的作用是什么

    由于Java采用抢占式的线程调度算法,因此可能会出现某条线程常常获取到CPU控制权的情况,为了让某些优先级比较低的线程也能获取到CPU控制权,可以使用Thread.sleep(0)手动触发一次操作系统分配时间片的操作,这也是平衡CPU控制权的一种操作。

    什么是CAS

    CAS,全称为Compare and Swap,即比较-替换。假设有三个操作数:内存值V、旧的预期值A、要修改的值B,当且仅当预期值A和内存值V相同时,才会将内存值修改为B并返回true,否则什么都不做并返回false。当然CAS一定要volatile变量配合,这样才能保证每次拿到的变量是主内存中最新的那个值,否则旧的预期值A对某条线程来说,永远是一个不会变的值A,只要某次CAS操作失败,永远都不可能成功。

    什么是乐观锁和悲观锁

    乐观锁:乐观锁认为竞争不总是会发生,因此它不需要持有锁,将比较-替换这两个动作作为一个原子操作尝试去修改内存中的变量,如果失败则表示发生冲突,那么就应该有相应的重试逻辑。

    悲观锁:悲观锁认为竞争总是会发生,因此每次对某资源进行操作时,都会持有一个独占的锁,就像synchronized,不管三七二十一,直接上了锁就操作资源了。

    ConcurrentHashMap的并发度是什么?

    ConcurrentHashMap的并发度就是segment的大小,默认为16,这意味着最多同时可以有16条线程操作ConcurrentHashMap,这也是ConcurrentHashMap对Hashtable的最大优势,任何情况下,Hashtable能同时有两条线程获取Hashtable中的数据吗?

    ConcurrentHashMap的工作原理

    ConcurrentHashMap在jdk 1.6和jdk 1.8实现原理是不同的。

    jdk 1.6:

    ConcurrentHashMap是线程安全的,但是与Hashtablea相比,实现线程安全的方式不同。Hashtable是通过对hash表结构进行锁定,是阻塞式的,当一个线程占有这个锁时,其他线程必须阻塞等待其释放锁。ConcurrentHashMap是采用分离锁的方式,它并没有对整个hash表进行锁定,而是局部锁定,也就是说当一个线程占有这个局部锁时,不影响其他线程对hash表其他地方的访问。 
    具体实现:ConcurrentHashMap内部有一个Segment.

    jdk 1.8

    在jdk 8中,ConcurrentHashMap不再使用Segment分离锁,而是采用一种乐观锁CAS算法来实现同步问题,但其底层还是“数组+链表->红黑树”的实现。

    CyclicBarrier和CountDownLatch区别

    这两个类非常类似,都在java.util.concurrent下,都可以用来表示代码运行到某个点上,二者的区别在于:

    • CyclicBarrier的某个线程运行到某个点上之后,该线程即停止运行,直到所有的线程都到达了这个点,所有线程才重新运行;CountDownLatch则不是,某线程运行到某个点上之后,只是给某个数值-1而已,该线程继续运行。

    • CyclicBarrier只能唤起一个任务,CountDownLatch可以唤起多个任务

    • CyclicBarrier可重用,CountDownLatch不可重用,计数值为0该CountDownLatch就不可再用了。

    java中的++操作符线程安全么?

    不是线程安全的操作。它涉及到多个指令,如读取变量值,增加,然后存储回内存,这个过程可能会出现多个线程交差。

    你有哪些多线程开发良好的实践?

    1. 给线程命名

    2. 最小化同步范围

    3. 优先使用volatile

    4. 尽可能使用更高层次的并发工具而非wait和notify()来实现线程通信,如BlockingQueue,Semeaphore

    5. 优先使用并发容器而非同步容器.

    6. 考虑使用线程池


    关于volatile关键字

    可以创建Volatile数组吗?

    Java 中可以创建 volatile类型数组,不过只是一个指向数组的引用,而不是整个数组。如果改变引用指向的数组,将会受到volatile 的保护,但是如果多个线程同时改变数组的元素,volatile标示符就不能起到之前的保护作用了。

    volatile能使得一个非原子操作变成原子操作吗?

    一个典型的例子是在类中有一个 long 类型的成员变量。如果你知道该成员变量会被多个线程访问,如计数器、价格等,你最好是将其设置为 volatile。为什么?因为 Java 中读取 long 类型变量不是原子的,需要分成两步,如果一个线程正在修改该 long 变量的值,另一个线程可能只能看到该值的一半(前 32 位)。但是对一个 volatile 型的 long 或 double 变量的读写是原子。

    一种实践是用 volatile 修饰 long 和 double 变量,使其能按原子类型来读写。double 和 long 都是64位宽,因此对这两种类型的读是分为两部分的,第一次读取第一个 32 位,然后再读剩下的 32 位,这个过程不是原子的,但 Java 中 volatile 型的 long 或 double 变量的读写是原子的。volatile 修复符的另一个作用是提供内存屏障(memory barrier),例如在分布式框架中的应用。简单的说,就是当你写一个 volatile 变量之前,Java 内存模型会插入一个写屏障(write barrier)读一个 volatile 变量之前,会插入一个读屏障(read barrier)。意思就是说,在你写一个 volatile 域时,能保证任何线程都能看到你写的值,同时,在写之前,也能保证任何数值的更新对所有线程是可见的,因为内存屏障会将其他所有写的值更新到缓存。

    volatile类型变量提供什么保证?

    volatile 主要有两方面的作用:1.避免指令重排2.可见性保证.例如,JVM 或者 JIT为了获得更好的性能会对语句重排序,但是 volatile 类型变量即使在没有同步块的情况下赋值也不会与其他语句重排序。 volatile 提供 happens-before 的保证,确保一个线程的修改能对其他线程是可见的。某些情况下,volatile 还能提供原子性,如读 64 位数据类型,像 long 和 double 都不是原子的(低32位和高32位),但 volatile 类型的 double 和 long 就是原子的。


    关于集合

    Java中的集合及其继承关系

    关于集合的体系是每个人都应该烂熟于心的,尤其是对我们经常使用的List,Map的原理更该如此.这里我们看这张图即可: 

    更多内容可见集合类总结:

    http://write.blog.csdn.net/postedit/40826423

    poll()方法和remove()方法区别?

    poll() 和 remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是 remove() 失败的时候会抛出异常。

    LinkedHashMap和PriorityQueue的区别

    PriorityQueue 是一个优先级队列,保证最高或者最低优先级的的元素总是在队列头部,但是 LinkedHashMap 维持的顺序是元素插入的顺序。当遍历一个 PriorityQueue 时,没有任何顺序保证,但是 LinkedHashMap 课保证遍历顺序是元素插入的顺序。

    WeakHashMap与HashMap的区别是什么?

    WeakHashMap 的工作与正常的 HashMap 类似,但是使用弱引用作为 key,意思就是当 key 对象没有任何引用时,key/value 将会被回收。

    ArrayList和LinkedList的区别?

    最明显的区别是 ArrrayList底层的数据结构是数组,支持随机访问,而 LinkedList 的底层数据结构是双向循环链表,不支持随机访问。使用下标访问一个元素,ArrayList 的时间复杂度是 O(1),而 LinkedList 是 O(n)。

    ArrayList和Array有什么区别?

    1. Array可以容纳基本类型和对象,而ArrayList只能容纳对象。

    2. Array是指定大小的,而ArrayList大小是固定的

    ArrayList和HashMap默认大小?

    在 Java 7 中,ArrayList 的默认大小是 10 个元素,HashMap 的默认大小是16个元素(必须是2的幂)。这就是 Java 7 中 ArrayList 和 HashMap 类的代码片段。

    private static final int DEFAULT_CAPACITY = 10;
    
    //from HashMap.java JDK 7
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4// aka 16

     

    Comparator和Comparable的区别?

    Comparable 接口用于定义对象的自然顺序,而 comparator 通常用于定义用户定制的顺序。Comparable 总是只有一个,但是可以有多个 comparator 来定义对象的顺序。

    如何实现集合排序?

    你可以使用有序集合,如 TreeSet 或 TreeMap,你也可以使用有顺序的的集合,如 list,然后通过 Collections.sort() 来排序。

    如何打印数组内容

    你可以使用 Arrays.toString() 和 Arrays.deepToString() 方法来打印数组。由于数组没有实现 toString() 方法,所以如果将数组传递给 System.out.println() 方法,将无法打印出数组的内容,但是 Arrays.toString() 可以打印每个元素。

    LinkedList的是单向链表还是双向?

    双向循环列表,具体实现自行查阅源码。

    TreeMap是实现原理

    采用红黑树实现,具体实现自行查阅源码。

    遍历ArrayList时如何正确移除一个元素

    该问题的关键在于面试者使用的是 ArrayList 的 remove() 还是 Iterator 的 remove()方法。这有一段示例代码,是使用正确的方式来实现在遍历的过程中移除元素,而不会出现 ConcurrentModificationException 异常的示例代码。

    什么是ArrayMap?它和HashMap有什么区别?

    ArrayMap是Android SDK中提供的,非Android开发者可以略过。
    ArrayMap是用两个数组来模拟map,更少的内存占用空间,更高的效率。
    具体参考这篇文章:ArrayMap VS HashMap:http://lvable.com/?p=217%5D

    HashMap的实现原理

    1. HashMap概述: HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。 
    2. HashMap的数据结构: 在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。

    当我们往Hashmap中put元素时,首先根据key的hashcode重新计算hash值,根绝hash值得到这个元素在数组中的位置(下标),如果该数组在该位置上已经存放了其他元素,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放入链尾.如果数组中该位置没有元素,就直接将该元素放到数组的该位置上.

    需要注意Jdk 1.8中对HashMap的实现做了优化,当链表中的节点数据超过八个之后,该链表会转为红黑树来提高查询效率,从原来的O(n)到O(logn)

    你了解Fail-Fast机制吗?

    Fail-Fast即我们常说的快速失败,

    更多内容参看fail-fast机制:http://blog.csdn.net/chenssy/article/details/38151189

    Fail-fast和Fail-safe有什么区别

    Iterator的fail-fast属性与当前的集合共同起作用,因此它不会受到集合中任何改动的影响。Java.util包中的所有集合类都被设计为fail->fast的,而java.util.concurrent中的集合类都为fail-safe的。当检测到正在遍历的集合的结构被改变时,Fail-fast迭代器抛出ConcurrentModificationException,而fail-safe迭代器从不抛出ConcurrentModificationException。


    关于日期

    SimpleDateFormat是线程安全的吗?

    非常不幸,DateFormat 的所有实现,包括 SimpleDateFormat 都不是线程安全的,因此你不应该在多线程序中使用,除非是在对外线程安全的环境中使用,如 将 SimpleDateFormat 限制在 ThreadLocal 中。如果你不这么做,在解析或者格式化日期的时候,可能会获取到一个不正确的结果。因此,从日期、时间处理的所有实践来说,我强力推荐 joda-time 库。

    如何格式化日期?

    Java 中,可以使用 SimpleDateFormat 类或者 joda-time 库来格式日期。DateFormat 类允许你使用多种流行的格式来格式化日期。参见答案中的示例代码,代码中演示了将日期格式化成不同的格式,如 dd-MM-yyyy 或 ddMMyyyy。


    关于异常

    简单描述java异常体系

    相比没有人不了解异常体系,关于异常体系的更多信息可以见

    白话异常机制:http://blog.csdn.net/dd864140130/article/details/42504189

    什么是异常链

    详情直接参见上面的白话异常机制,不做解释了。

    throw和throws的区别

    throw用于主动抛出java.lang.Throwable 类的一个实例化对象,意思是说你可以通过关键字 throw 抛出一个 Error 或者 一个Exception,如:throw new IllegalArgumentException(“size must be multiple of 2″)
    而throws 的作用是作为方法声明和签名的一部分,方法被抛出相应的异常以便调用者能处理。Java 中,任何未处理的受检查异常强制在 throws 子句中声明。


    关于序列化

    Java 中,Serializable 与 Externalizable 的区别

    Serializable 接口是一个序列化 Java 类的接口,以便于它们可以在网络上传输或者可以将它们的状态保存在磁盘上,是 JVM 内嵌的默认序列化方式,成本高、脆弱而且不安全。Externalizable 允许你控制整个序列化过程,指定特定的二进制格式,增加安全机制。


    关于JVM

    JVM特性

    平台无关性. 
    Java语言的一个非常重要的特点就是与平台的无关性。而使用Java虚拟机是实现这一特点的关键。一般的高级语言如果要在不同的平台上运行,至少需要编译成不同的目标代码。而引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用模式Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。

    简单解释一下类加载器

    有关类加载器一般会问你四种类加载器的应用场景以及双亲委派模型,

    更多的内容参看深入理解JVM加载器:

    http://blog.csdn.net/dd864140130/article/details/49817357

    简述堆和栈的区别

    VM 中堆和栈属于不同的内存区域,使用目的也不同。栈常用于保存方法帧和局部变量,而对象总是在堆上分配。栈通常都比堆小,也不会在多个线程之间共享,而堆被整个 JVM 的所有线程共享。

    简述JVM内存分配

    1. 基本数据类型比变量和对象的引用都是在栈分配的。

    2. 堆内存用来存放由new创建的对象和数组。

    3. 类变量(static修饰的变量),程序在一加载的时候就在堆中为类变量分配内存,堆中的内存地址存放在栈中。

    4. 实例变量:当你使用java关键字new的时候,系统在堆中开辟并不一定是连续的空间分配给变量,是根据零散的堆内存地址,通过哈希算法换算为一长串数字以表征这个变量在堆中的”物理位置”,实例变量的生命周期–当实例变量的引用丢失后,将被GC(垃圾回收器)列入可回收“名单”中,但并不是马上就释放堆中内存。

    5. 局部变量: 由声明在某方法,或某代码段里(比如for循环),执行到它的时候在栈中开辟内存,当局部变量一但脱离作用域,内存立即释放。


    其他

    java当中采用的是大端还是小端?

    XML解析的几种方式和特点

    DOM, SAX, PULL三种解析方式:

    • DOM:消耗内存:先把xml文档都读到内存中,然后再用DOM API来访问树形结构,并获取数据。这个写起来很简单,但是很消耗内存。要是数据过大,手机不够牛逼,可能手机直接死机

    • SAX:解析效率高,占用内存少,基于事件驱动的:更加简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时通知事件处理函数,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。

    • PULL:与 SAX 类似,也是基于事件驱动,我们可以调用它的next()方法,来获取下一个解析事件(就是开始文档,结束文档,开始标签,结束标签),当处于某个元素时可以调用XmlPullParser的getAttributte()方法来获取属性的值,也可调用它的nextText()获取本节点的值。

    JDK 1.7特性

    然 JDK 1.7 不像 JDK 5 和 8 一样的大版本,但是,还是有很多新的特性,如 try-with-resource 语句,这样你在使用流或者资源的时候,就不需要手动关闭,Java 会自动关闭。Fork-Join 池某种程度上实现 Java 版的 Map-reduce。允许 Switch 中有 String 变量和文本。菱形操作符(<>)用于类型推断,不再需要在变量声明的右边申明泛型,因此可以写出可读写更强、更简洁的代码。

    JDK 1.8特性

    java 8 在 Java 历史上是一个开创新的版本,下面 JDK 8 中 5 个主要的特性: 
    Lambda 表达式,允许像对象一样传递匿名函数 
    Stream API,充分利用现代多核 CPU,可以写出很简洁的代码 
    Date 与 Time API,最终,有一个稳定、简单的日期和时间库可供你使用 
    扩展方法,现在,接口中可以有静态、默认方法。 
    重复注解,现在你可以将相同的注解在同一类型上使用多次。

    Maven和ANT有什么区别?

    虽然两者都是构建工具,都用于创建 Java 应用,但是 Maven 做的事情更多,在基于“约定优于配置”的概念下,提供标准的Java 项目结构,同时能为应用自动管理依赖(应用中所依赖的 JAR 文件。

    JDBC最佳实践

    • 优先使用批量操作来插入和更新数据

    • 使用PreparedStatement来避免SQL漏洞

    • 使用数据连接池

    • 通过列名来获取结果集

    IO操作最佳实践

    • 使用有缓冲的IO类,不要单独读取字节或字符

    • 使用NIO和NIO 2或者AIO,而非BIO

    • 在finally中关闭流

    • 使用内存映射文件获取更快的IO

    来源于:https://blog.csdn.net/dd864140130/article/details/55833087

     

     

     

     

     

     


     

    展开全文
  • 知识点(持续更新)

    2020-09-21 12:01:09
    Java中的引用类型分类以及使用场景 https://blog.csdn.net/u011702479/article/details/82263040
  • 数据结构知识点汇总

    万次阅读 多人点赞 2018-07-18 15:44:21
    1、用链表表示线性表的优点是(便于插入和删除操作) 2、单链表中,增加头结点的目的是(方便运算的实现) 3、栈和队列的共同特点是(只允许在端点处插入和删除元素) 4、栈通常采用的两种存储结构是(线性存储...
  • 总结 离散数学知识点

    万次阅读 多人点赞 2014-07-16 18:51:48
    总结 离散数学知识点 第二章 命题逻辑 1.→,前键为真,后键为假才为假;—>,相同为真,不同为假; 2.主析取范式:极小项(m)之和;主合取范式:极大项(M)之积; 3.求极小项时,命题变元的肯定为1,否定为0,...
  • 明天就要考试了,来一波知识点整理。都会了,期末考试你不过你来找我! 第一章 1.按微处理器的字节分类 4 位微处理器 8 位微处理器 16位微处理器 32位微处理器 2.这个必须背,不是简答就是简答,肯定出...
  • Java面试知识点汇总

    万次阅读 多人点赞 2020-06-26 15:21:23
    为了找到心仪的工作而努力吧 最近在刷各种面经,把学会的知识点汇总一下以便查漏补缺: 未完待续…
  • 计算机组成原理核心知识点总结&面试笔试要点

    万次阅读 多人点赞 2020-06-13 19:52:06
    作为一名计算机专业的学生,计算机组成原理、计算机网络、操作系统这三门课程可以说是专业核心基础课,是至...而且很多互联网公司在笔试和面试中都会涉及到这三门课程的知识点,因此我通过视频学习对这三门课程就行...
  • Java基础面试知识点总结

    万次阅读 多人点赞 2019-12-29 22:40:14
    笔者之前对每部分的内容 对做了比较深入的学习以及代码实现,基本上比较全面地讲述了每一个Java基础知识点,当然可能有些遗漏和错误,还请读者指正。 更多关于Java后端学习的内容请到我的CSDN博客上查看: ...
  • 2020年江西信息技术高考考点知识点、历年真题解析 复习资料 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2020年江西信息技术第一...
  • C++知识点总结

    万次阅读 多人点赞 2018-05-25 12:04:16
     看了两本书,自考课本(编号04737)和C++程序设计谭浩强版的,我比较推荐后一本,浅显易懂,知识点多,例子多,可以自己多多动手写一写。 下面对学习过程中需要注意的知识点做了一些总结和导图:
  • C++复习大全(各种知识点

    万次阅读 多人点赞 2018-05-28 20:42:29
    这篇博客是我之前的一个礼拜复习总结的各种知识点,可能有些多,其中的一些观点是来自于《Effective C++》和《C++编程思想》,这两本书中的知识给了我很多启发,也让我懂得了许多不一样的知识点,我连带我的认识以及...
  • 剑指Offer——笔试题+知识点总结

    万次阅读 2016-09-25 11:40:29
    剑指Offer——笔试题+知识点总结情景回顾 时间:2016.9.23 12:00-14:00 19:00-21:00 地点:山东省网络环境智能计算技术重点实验室 事件:笔试 注意事项:要有大局观,该舍弃的还是要舍弃,不要在一道编程题上占用...
  • C语言知识点总结

    万次阅读 多人点赞 2018-08-24 08:09:48
    C语言最重要的知识点 总体上必须清楚的: 1)程序结构是三种: 顺序结构 、选择结构(分支结构)、循环结构。 2)读程序都要从main()入口, 然后从最上面顺序往下读(碰到循环做循环,碰到选择做选择),有且只有一个main...
  • 雷达原理 知识点汇总

    万次阅读 多人点赞 2018-05-16 19:30:05
    雷达原理知识点汇总 第一章 绪论 1、雷达概念(Radar): radar的音译,“Radio Detection and Ranging ”的缩写。原意是“无线电探测和测距”,即用无线电方法发现目标并测定它们在空间的位置。 2、雷达工作...
  • 剑指Offer——网易校招内推笔试题+模拟题知识点总结前言 2016.8.2 19:00网易校招内推笔试开始进行。前天晚上利用大约1小时时间完成了测评(这个必须做,关切到你能否参与面试)。上午利用2小时时间做了下模拟题,模拟...
  • 数据结构与算法知识点总结—思维导图

    万次阅读 多人点赞 2020-04-20 22:50:54
    数据结构与算法是学习编程者的必修课,下面是我学习完之后的知识点梳理与总结。 本来用xmind做的时候把重要知识点都附了博客链接,但是xmind导出来后打不开了。 不用担心我把相关内容放在了数据结构专栏里。 ...
1 2 3 4 5 ... 20
收藏数 1,476,370
精华内容 590,548
关键字:

知识点