2018届秋季校招Java面试题总结(二)

2018届秋季校招考试题总结系列是在 本菜 面挂一万场后记下的面试题。记下以供闲暇学习之。

1. 关于网络协议(趋势科技、联想、58到家面试)

    答:TPC/IP 协议是传输层协议,主要解决数据如何在网络中传输,而HTTP 是应用层协议,主要解决如何包装数据。关于TCP/IP 和HTTP 协议的关系,网络有一段比较容易理解的介绍:“我们在传输数据时,可以只使用(传输层)TCP/IP 协议,但是那样的话,如果没有应用层,便无法识别数据内容,如果想要使传输的数据有意义,则必须使用到应用层协议,应用层协议有很多,比如HTTP、FTP、TELNET 等,也可以自己定义应用层协议。WEB 使用HTTP 协议作应用层协议,以封装HTTP 文本信息,然后使用TCP/IP 做传输层协议将它发到网络上。

    TCP/IP 代表传输控制协议/网际协议,指的是一系列协议。“IP”代表网际协议,TCP 和UDP 使用该协议从一个网络传送数据包到另一个网络。把IP 想像成一种高速公路,它允许其它协议在上面行驶并找到到其它电脑的出口。TCP 和UDP 是高速公路上的“卡车”,它们携带的货物就是像HTTP,文件传输协议FTP 这样的协议等。所以,TCP 和UDP 是FTP,HTTP 和SMTP 之类使用的传输层协议。

    虽然TCP 和UDP 都是用来传输其他协议的,它们却有一个显著的不同:TCP 提供有保证的数据传输,而UDP 不提供。这意味着TCP 有一个特殊的机制来确保数据安全的不出错的从一个端点传到另一个端点,而UDP 不提供任何这样的保证。

    OSI 模型中的位置:(趋势)
      7 应用层例如HTTP、SMTP、SNMP、FTP、Telnet、SIP、SSH、NFS、RTSP、XMPP、Whois、ENRP
      6 表示层例如XDR、ASN.1、SMB、AFP、NCP
      5 会话层例如ASAP、TLS、SSH、ISO 8327 / CCITTX.225、RPC、NetBIOS、ASP、Winsock、BSD sockets
      4 传输层例如TCP、UDP、RTP、SCTP、SPX、ATP、IL
      3 网络层例如IP、ICMP、IGMP、IPX、BGP、OSPF、RIP、IGRP、EIGRP、ARP、RARP、X.25
      2 数据链路层例如以太网、令牌环、HDLC、帧中继、ISDN、ATM、IEEE 802.11、FDDI、PPP
      1 物理层例如线路、无线电、光纤、信鸽
    --HTTP 协议的几个重要概念:(58到家)

      ①.连接(Connection):一个传输层的实际环流,它是建立在两个相互通讯的应用程序之间。

      ②.消息(Message):HTTP 通讯的基本单位,包括一个结构化的八元组序列并通过连接传输。

      ③.请求(Request):一个从客户端到服务器的请求信息包括应用于资源的方法、资源的标识符和协议的版本号。
      ④.响应(Response):一个从服务器返回的信息包括HTTP 协议的版本号、请求的状态(例如“成功”或“没找到”)和文档的MIME 类型。
      ⑤.资源(Resource):由URI 标识的网络数据对象或服务。
      ⑥.实体(Entity):数据资源或来自服务资源的回映的一种特殊表示方法,它可能被包围在一个请求或响应信息中。一个实体包括实体头信息和实体的本身内容。
      ⑦.客户机(Client):一个为发送请求目的而建立连接的应用程序。
      ⑧.用户代理(Useragent):初始化一个请求的客户机。它们是浏览器、编辑器或其它用户工具。
      ⑨.服务器(Server):一个接受连接并对请求返回信息的应用程序。
      ⑩.源服务器(Originserver):是一个给定资源可以在其上驻留或被创建的服务器。
      ⑪.代理(Proxy):一个中间程序,它可以充当一个服务器,也可以充当一个客户机,为其它客户机建立请求。请求是通过可能的翻译在内部或经过传递到其它的服务器中。一个代理在发送请求信息之前,必须解释并且如果可能重写它。 代理经常作为通过防火墙的客户机端的门户,代理还可以作为一个帮助应用来通过协议处理没有被用户代理完成的请求。
      ⑫.网关(Gateway):一个作为其它服务器中间媒介的服务器。与代理不同的是,网关接受请求就好象对被请求的资源来说它就是源服务器;发出请求的客户机并没有意识到它在同网关打交道。 网关经常作为通过防火墙的服务器端的门户,网关还可以作为一个协议翻译器以便存取那些存储在非HTTP系统中的资源。
      ⑬.通道(Tunnel):是作为两个连接中继的中介程序。一旦激活,通道便被认为不属于HTTP 通讯,尽管通道可能是被一个HTTP 请求初始化的。当被中继的连接两端关闭时,通道便消失。当一个门户(Portal)必须存在或中介(Intermediary)不能解释中继的通讯时通道被经常使用。
      ⑭.缓存(Cache):反应信息的局域存储。
    --发送请求:打开一个连接后,客户机把请求消息送到服务器的停留端口上,完成提出请求动作。URL=协议名称+宿主名+目录与文件名。请求行中的方法描述指定资源中应该执行的动作,常用的方法有GET、HEAD 和POST。
    --发送响应:服务器在处理完客户的请求之后,要向客户机发送响应消息。 (联想)
      状态码表示响应类型(详细参见: http://blog.csdn.net/liuxinghao/article/details/50477415
      1×× 保留
      2×× 表示请求成功地接收
      3×× 为完成请求客户需进一步细化请求
      4×× 客户错误

      5×× 服务器错误

      (默写几个吧。200 请求成功、300请求文档已找到,可进一步执行多种选择进行重定向、400请求出现语法错误、401请求需要身份验证、403请求拒绝、404请求页面不存在、500服务器内部错误、503服务器暂时不能提供服务--可能过载了、505服务器不支持当前请求的http版本)


2. Spring 事务隔离级别

    答:①. 事务的隔离级别
      -> ISOLATION_DEFAULT : 这是一个PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别. 另外四个与JDBC 的隔离级别相对应.
      -> ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像
。(ISOLATION_READ_UNCOMMITTED 最低隔离级别脏读、不可重复读、幻读)
      -> ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。
      -> ISOLATION_REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据
外,还保证了避免下面的情况产生(不可重复读)。
      -> ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。
    ②. 补充:什么是脏数据,脏读,不可重复读,幻觉读?凤凰面试
      脏读: 指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据, 那么另外一个事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的。
      不可重复读: 指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
      幻觉读: 指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。

    ③. 另外,事务的传播属性:key属性确定代理应该给哪个方法增加事务行为。这样的属性最重要的部份是传播行为。有以下选项可供使用:
      PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。(比如说, ServiceB.methodB 的事务级别定义为PROPAGATION_REQUIRED, 那么由于执行ServiceA.methodA 的时候,ServiceA.methodA 已经起了事务, 这时调用ServiceB.methodB ,ServiceB.methodB 看到自己已经运行在ServiceA.methodA 的事务内部,就不再起新的事务。而假如ServiceA.methodA 运行的时候发现自己没有在事务中,ServiceB.methodB 就会为自己分配一个事务。这样,在ServiceA.methodA 或者在ServiceB.methodB 内的任何地方出现异常, 事务都会被回滚。即使ServiceB.methodB 的事务已经被提交, 但是ServiceA.methodA 在接下来fail 要回滚,ServiceB.methodB 也要回滚)
      PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
      PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
      PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
      PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
      PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
      另外,PROPAGATION_NESTED -- 理解Nested 的关键是savepoint。他与PROPAGATION_REQUIRES_NEW 的区别是,PROPAGATION_REQUIRES_NEW 另起一个事务,将会与他的父事务相互独立,而Nested 的事务和他的父事务是相依的,他的提交是要等和他的父事务一块提交的。也就是说,如果父事务最后回滚,他也要回滚的。
而Nested 事务的好处是他有一个savepoint。也就是说ServiceB.methodB 失败回滚,那么ServiceA.methodA也会回滚到savepoint 点上,ServiceA.methodA 可以选择另外一个分支,比如ServiceC.methodC,继续执行,来尝试完成自己的事务。但是这个事务并没有在EJB 标准中定义。


3. ConcurrentHashMap(联想、讯飞)
    答:JDK1.6 版本:①.ConcurrentHashMap 结构:ConcurrentHashMap 将数据分成一段一段存储,给每一段数据配一把锁,当一个线程获得锁互斥访问一个段数据时,其他段的数据也可被其他线程访问;每个Segment 拥有一把可重入锁, 因此ConcurrentHashMap 的分段锁数目即为Segment 数组长度。
      ConcurrentHashMap 结构:每一个segment 都是一个HashEntry<K,V>[] table,table 中的每一个元素本质上都是一个HashEntry 的单向队列(单向链表实现)。
      ②.锁分离实现:当一个线程访问Node/键值对数据时,必须获得与它对应的segment 锁,其他线程可以访问其他Segment 中的数据(锁分离);
      补充:乐观锁与悲观锁
        悲观锁比如synchronized 锁,为确保其他线程不会干扰当前线程工作,因此挂起其他需要锁的线程,等待持有锁的线程释放;
        乐观锁总是假设没有冲突发生去做操作,如果检测到冲突就失败重试,直到成功为止;
      ③.无锁算法:CAS 算法,CAS(Compare And Swap):CAS 算法包含三个参数CAS(V,E, N),判断预期值E 和内存旧值是否相同(Compare),如果相等用新值N 覆盖旧值V(Swap),否则失败;当多个线程尝试使用CAS 同时更新同一个变量时,只有其中一个线程能更新变量的值,其他线程失败(失败线程不会被阻塞,而是被告知“失败”,可以继续尝试);
      优点:CAS 在硬件层面可以被编译为机器指令执行,因此性能高于基于锁占有方式实现线程安全;
    JDK1.8 版本: ①.ConcurrentHashMap 结构:JDK 1.8 取消类segments字段,直接用table 数组存储键值对,JDK1.6 中每个bucket 中键值对组织方式是单向链表,查找复杂度是O(n),JDK1.8 中当链表长度超过TREEIFY_THRESHOLD 时,链表转换为红黑树,查询复杂度可以降低到O(log n),改进性能
     ②.锁分离实现:JDK1.8 中,一个线程每次对一个桶(链表or 红黑树)进行加锁,其他线程仍然可以访问其他桶;
     ③.线程安全:ConcurrentHashMap 底层数据结构与HashMap 相同,仍然采用table 数组+链表+红黑树结构;一个线程进行put/remove 操作时,对桶的头元素(链表or 红黑树)加上synchronized 独占锁;ConcurrentHashMap 采用CAS 算法保证线程安全;(与hashtable的区别是,hashtable采用的是对整个put方法加synchronized,所以hashtable效率低)
     详细:http://blog.csdn.net/Juwenzhe_HEBUT/article/details/77882752


4. socket 通信流程
  答:socket 是"打开—读/写—关闭"模式的实现,以使用TCP协议通讯的socket 为例,其交互流程大概是这样子的:

     服务器根据地址类型(ipv4,ipv6)、socket 类型、协议创建socket

     服务器为socket 绑定ip 地址和端口号
     服务器socket 监听端口号请求,随时准备接收客户端发来的连接,这时候服务器的socket 并没有被打开
     客户端创建socket
     客户端打开socket,根据服务器ip 地址和端口号试图连接服务器socket
     服务器socket 接收到客户端socket 请求,被动打开,开始接收客户端请求,直到客户端返回连接信息。这时候socket 进入阻塞状态,所谓阻塞即accept()方法一
直到客户端返回连接信息后才返回,开始接收下一个客户端谅解请求
     客户端连接成功,向服务器发送连接状态信息
     服务器accept 方法返回,连接成功
     客户端向socket 写入信息
     服务器读取信息
     客户端关闭
     服务器端关闭
   补充:三次握手
     在TCP/IP 协议中,TCP 协议通过三次握手建立一个可靠的连接
      第一次握手:客户端尝试连接服务器,向服务器发送syn包(同步序列编号Synchronize Sequence Numbers),syn=j,客户端进入SYN_SEND 状态等待服务器确认
      第二次握手: 服务器接收客户端syn 包并确认(ack=j+1),同时向客户端发送一个SYN 包(syn=k),即SYN+ACK 包,此时服务器进入SYN_RECV 状态
      第三次握手:第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED 状态,完成三次
握手
      服务器socket 与客户端socket 建立连接的部分其实就是大名鼎鼎的三次握手


5. java 六大原则
答:①.类单一职责:一个类只负责一项职责,不要存在多余一个职责导致类的变更。比如:类A 负责两个不同的职责,b,c 职责。由于b 职责需求发生变化而需要改变A 类,原本运行正常的c 职责出现故障。
    ②.里氏替换原则:1》.子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。2》.子类中可以增加自己特有的方法。3》.当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。4》.当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。总之尽量不要重写父类已经实现的方法,可以用接口其它方法绕过去。
    ③.依赖倒置原则:高层模块不应该依赖底层模块,都应该依赖抽象;抽象不应该依赖细节,细节应该依赖抽象。总之:多用抽象的接口来描述要做的动作,降低实现这个动作的事务之间的耦合度。(各自拥有各自的接口,不要放在一起使用,降低耦合性)
    ④.接口隔离原则:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖建立在最小的接口上。总之就是一个接口尽量完功能的单一,不要让一个接口承担过多的责任。
    ⑤.迪米特法则:经查最早是在1987 年由美国Northeastern University 的Ian Holland 提出。一个类尽量封装自己,除了对外提供public 方法之外,其它的不对外泄露信息。只与自己的成员变量和参数打交道,不与其它打交道。
    ⑥.开闭原则:对扩展开放,修改关闭。尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。

6. 死锁产生的原因及四个必要条件(中科曙光)
    答: 产生死锁的原因主要是:
     (1) 因为系统资源不足。
     (2) 进程运行推进的顺序不合适。
     (3) 资源分配不当等。
    如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。
    产生死锁的四个必要条件:
     (1) 互斥条件:一个资源每次只能被一个进程使用。
     (2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
     (3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
     (4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
    这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。
    死锁的解除与预防:

      理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和解除死锁。所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态的情况下占用资源。因此,对资源的分配要给予合理的规划。


7. 加密

    答:对称加密(也叫私钥加密)指加密和解密使用相同密钥的加密算法。有时又叫传统密码算法,就是加密密钥能够从解密密钥中推算出来,同时解密密钥也可以从加密密钥中推算出来。DES 算法,3DES 算法,TDEA 算法,Blowfish 算法,RC5 算法,IDEA 算法。
    非对称:非对称加密算法需要两个密钥来进行加密和解密,这两个秘钥是公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥)。在非对称加密中使用的主要算法有:RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)等。


8. 抽象类与接口的异同(StarTime面试)

    答:①.抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。
    ②.抽象类要被子类继承,接口要被类实现。
    ③.接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现
    ④.接口里定义的变量只能是公共的静态的常量(public static final),抽象类中的变量是普通变量。
    ⑤.抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。
    ⑥.抽象方法只能申明,不能实现。abstract void abc();不能写成abstract void abc(){}。
    ⑦.抽象类里可以没有抽象方法
    ⑧.如果一个类里有抽象方法,那么这个类只能是抽象类
    ⑨.抽象方法要被实现,所以不能是静态的,也不能是私有的。
    ⑩.接口可继承接口,并可多继承接口,但类只能单根继承。


9. JAVA8 新特性
    答:一、接口的默认方法
       Java 8 允许我们给接口添加一个非抽象的方法实现,只需要使用default 关键字即可,这个特征又叫做扩展方法,示例如下:
          interface Formula {
            double calculate(int a);
            default double sqrt(int a) {
               return Math.sqrt(a);
            }
          }
      Formula 接口在拥有calculate 方法之外同时还定义了sqrt 方法,实现了Formula 接口的子类只需要实现一个calculate 方法,默认方法sqrt 将在子类上可以直接使用。
          Formula formula = new Formula() {
            @Override
            public double calculate(int a) {
            return sqrt(a * 100);
            }
          };
          formula.calculate(100); // 100.0
          formula.sqrt(16); // 4.0
     二、Lambda 表达式
      首先看看在老版本的Java 中是如何排列字符串的:
         List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
           Collections.sort(names, new Comparator<String>(){
             @Override
             public int compare(String a, String b) {
                return b.compareTo(a);
             }
         });
      只需要给静态方法Collections.sort 传入一个List对象以及一个比较器来按指定顺序排列。通常做法都是创建一个匿名的比较器对象然后将其传递给sort 方法。在Java 8 中你就没必要使用这种传统的匿名对象的方式了,Java 8 提供了更简洁的语法,lambda 表达式:
      Collections.sort(names, (String a, String b) -> {
         return b.compareTo(a);
      });
      实际上还可以写得更短:Collections.sort(names, (String a, String b) ->b.compareTo(a));
      对于函数体只有一行代码的,可以去掉大括号{}以及return 关键字,但是你还可以写得更短点:Collections.sort(names, (a, b) ->b.compareTo(a));
      Java 编译器可以自动推导出参数类型,所以你可以不用再写一次类型。
     三、函数式接口
      Lambda 表达式是如何在java 的类型系统中表示的呢?每一个lambda 表达式都对应一个类型,通常是接口类型。而“函数式接口”是指仅仅只包含一个抽象方法的接口,每一个该类型的lambda 表达式都会被匹配到这个抽象方法因为默认方法不算抽象方法,所以你也可以给你的函数式接口添加默认方法。我们可以将lambda 表达式当作任意只包含一个抽象方法的接口类型,确保你的接口一定达到这个要求,你只需要给你的接口添加@FunctionalInterface 注解,编译器如果发现你标注了这个注解的接口有多于一个抽
象方法的时候会报错的。
     四、支持多重Annotation 注解(犯懒了,以后用到再说。。。)


10. JAVA9 新特性(摘自脚本之家)

    答:1. Jigsaw 项目;模块化源码
    2. 简化进程API
    3. 轻量级JSON API
    4. 钱和货币的API
    5. 改善锁争用机制
    6. 代码分段缓存
    7. 智能Java 编译, 第二阶段
    8. HTTP 2.0 客户端
    9. Kulla 计划: Java 的REPL 实现
    Jav1.9 新特性
     1. Jigsaw 项目;模块化源码:Jigsaw 项目是为了模块化Java 代码、将JRE 分成可相互协作的组件,这也是Java 9 众多特色种的一个。JEP是迈向Jigsaw 四步中的第一步,它不会改变JRE 和JDK 的真实结构。JEP 是为了模块化JDK 源代码,让编译系统能够模块编译并在构建时检查模块边界。这个项目原本是随Java 8 发布的,但由于推迟,所以将把它加到Java9.一旦它完成,它可能允许根据一个项目需求自定义组件从而减少rt.jar 的大小。在JDK 7 和JDK 8 的rt.jar包中有大约20,000 个类,但有很多类在一些特定的环境里面并没有被用到(即使在Java 8 的紧凑分布特性中已经包含了一部分解决方法也存在着类冗余)。这么做是为了能让Java 能够容易应用到小型计算设备(比如网络设备)中,提高它的安全和性能,同时也能让开发者更容易构建和维护这些类库。
      2. 简化进程API:截止到目前,Java 控制与管理系统进程的能力是有限的。举个例子,现在为了简便获取你程序的进程PID,你要么调用本地程序要么要自己使用一些变通方案。更多的是,每个(系统)平台需要有一个不同实现来确保你能获得正确的结果。期望代码能获取Linux PIDS,现在是如下方式:
      在Java 9 中,可以变换成如下方式(支持所有的操作系统):这次更新将会扩展Java 与操作系统的交互能力:新增一些新的直接明了的方法去处理PIDs,进程名字和状态以及枚举多个JVM 和进程以及更多事情。
      3. 轻量级JSON API:目前有多种处理JSON 的Java 工具,但JSON API 独到之处在于JSON API 将作为Java 语言的一部分,轻量并且运用Java 8 的新特性。它将放在java.util 包里一起发布(但在JSR 353 里面的JSON 是用第三方包或者其他的方法处理的).
      4. 钱和货币的API:在Java 8 引进了日期和时间的API 之后, Java 9 引入了新的货币API, 用以表示货币, 支持币种之间的转换和各种复杂运算. 关于这个项目的具体情况, 请访问https://github.com/JavaMoney,里面已经给出了使用说明和示例
      5. 改善锁争用机制:锁争用是限制许多Java 多线程应用性能的瓶颈. 新的机制在改善Java 对象监视器的性能方面已经得到了多种基准(benchmark)的验证, 其中包括Volano. 测试中通讯服务器开放了海量的进程来连接客户端, 其中有很多连接都申请同一个资源, 以此模拟重负荷日常应用.通过诸如此类的压力测试我们可以估算JVM 的极限吞吐量(每秒的消息数量). JEP 在22 种不同的测试中都得到了出色的成绩, 新的机制如果能在Java 9 中得到应用的话, 应用程序的性能将会大大提升.
      6. 代码分段缓存:Java 9 的另一个性能提升来自于JIT(Just-in-time)编译器. 当某段代码被大量重复执行的时候, 虚拟机会把这段代码编译成机器码(native code)并储存在代码缓存里面, 进而通过访问缓存中不同分段的代码来提升编译器的效率.和原来的单一缓存区域不同的是, 新的代码缓存根据代码自身的生命周期而分为三种:
         永驻代码(JVM 内置/ 非方法代码)
         短期代码(仅在某些条件下适用的配置性(profiled)代码)
         长期代码(非配置性代码)
      缓存分段会在各个方面提升程序的性能, 比如做垃圾回收扫描的时候可以直接跳过非方法代码(永驻代码), 从而提升效率.
      7. 智能Java 编译, 第二阶段智能Java 编译工具sjavac 的第一阶段开始于JEP 139 这个项目, 用于在多核处理器上提升JDK 的编译速度.现在这个项目已经进入第二阶段(JEP 199), 目的是改进sjavac 并让其成为取代目前JDK 编译工具javac 的Java 默认的通用编译工具.
      8. HTTP 2.0 客户端:HTTP 2.0 标准虽然还没正式发布, 但是已经进入了最终审查阶段, 预计可以在Java 9 发布之前审查完毕. JEP110 将会重新定义并实现一个全新的Java HTTP 客户端, 用来取代现在的HttpURLConnection, 同时也会实现HTTP 2.0 和网络接口(原文websockets). 它现在还没被JEP 正式认可但我们希望在Java 9 中包含这一项目的内容.官方的HTTP 2.0 RFC(Request for Comments, 官方技术讨论/会议记录等等的一系列文档记录)预订于2015年2 月发布, 它是基于Google 发布的SPDY(Speedy, 快速的)协议. 基于SPDY 协议的网络相对于基于HTTP1.1 协议的网络有11.81%到47.7%之间的显著提速, 现在已经有浏览器实现了这个协议.

      9. Kulla 计划: Java 的REPL 实现这个取名为Kulla 的项目最近宣布将于2015 年4 月整合测试, 虽然已经不太有希望能赶上Java 9 的发布, 但如果进度快的话或许刚好能赶上. 现在Java 并没有来自官方的REPL(Read-Eval-Print-Loop)方式, 也就是说现在如果你想要跑几行Java 代码做一个快速的测试, 你仍然需要把这几行代码封装在项目或者方法里面. 虽然在一些流行的IDE 里面有Java REPL 工具, 但它们并没有官方支持, 而Kulla 项目或许就能成为Java 官方发布的REPL 解决方案.


11. Git 是目前世界上最先进的分布式版本控制系统(没有之一)。
    SVN 是集中式的版本控制系统,而Git 是分布式版本控制系统,集中式和分布式版本控制系统有什么区别呢?

      先说集中式版本控制系统,版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器。集中式版本控制系统最大的毛病就是必须联网才能工作,如果在局域网内还好,带宽够大,速度够快,可如果在互联网上,遇到网速慢的话,可能提交一个10M 的文件就需要5 分钟。那分布式版本控制系统与集中式版本控制系统有何不同呢?首先,分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。既然每个人电脑上都有一个完整的版本库,那多个人如何协作呢?比方说你在自己电脑上改了文件A,你的同事也在他的电脑上改了文件A,这时,你们俩之间只需把各自的修改推送给对方,就可以互相看到对方的修改了
      和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多,因为每个人电脑里都有完整的版本库,某一个人的电脑坏掉了不要紧,随便从其他人那里复制一个就可以了。而集中式版本控制系统的中央服务器要是出了问题,所有人都没法干活了。在实际使用分布式版本控制系统的时候,其实很少在两人之间的电脑上推送版本库的修改,因为可能你们俩不在一个局域网内,两台电脑互相访问不了,也可能今天你的同事病了,他的电脑压根没有开机。因此,分布式版本控制系统通常也有一台充当“中央服务器”的
电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已。分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。其他版本控制系统如SVN 等都有分支管理,但是用过之后你会发现,这些版本控制系统创建和切换分支比蜗牛还慢,简直让人无法忍受,结果分支功能成了摆设,大家都不去用。
     Git 的分支是与众不同的,无论创建、切换和删除分支,Git 在1 秒钟之内就能完成!无论你的版本库是1 个文件还是1 万个文件


12. Spring 好处与优点及缺点
    答:使用Spring 有什么好处?
    (1)Spring 能有效地组织你的中间层对象。
    (2)Spring 能消除在许多工程中常见的对Singleton 的过多使用。
    (3)Spring 能消除各种各样自定义格式的属性文件的需要,使配置信息一元化。
    (4)Spring 能够帮助我们真正意义上实现针对接口编程。
    (5)在Spring 应用中的大多数业务对象没有依赖于Spring。
    (6)使用Spring 构建的应用程序易于单元测试。
    (7)Spring 支持JDBC 和O/R Mapping 产品(Hibernate)
    (8)MVC Web 框架,提供一种清晰,无侵略性的MVC 实现方式。
    (9)JNDI 抽象层,便于改变实现细节,可以方便地在远程服务和本地服务间切换。
    (10)简化访问数据库时的例外处理。
    (11)Spring 能使用AOP 提供声明性事务管理,可以不直接操作JTA 也能够对事务进行管理。
    (12)提供了JavaMail 或其他邮件系统的支持。
    优点:
    Spring 的开发者可以避免使用重量级容器开发EJB 时的缺点:
    (1)带有侵略性的API。(代码依赖于EJB)
    (2)对容器的依赖。(代码不能在EJB 容器之外工作)
    (3)提供固定的一组机能,不具有配置能力。
    (4)不同的产品,部署过程不同,不易通用。
    (5)启动时间长。
    针对以上问题,Spring 采用了IoC 使代码对Spring 的依赖减少,根据Web 应用,小应用程序,桌面应用程的不同,对容器的依赖程度也不同。Spring 将管理的Bean 作为
POJO(Plain Old Java Object)进行控制,通过AOPInterceptor 能够增加其它的功能。除了Spring 以外的轻量级容器还有PicoContainer,(不是轻量级容器)对Bean 的生命周期进行管理的还有ApacheAvalon Project 的Avalon 等。
    总结:Spring 的核心思想便是IoC 和AOP,Spring 本身是一个轻量级容器,和EJB 容器不同,Spring 的组件就是普通的Java Bean,这使得单元测试可以不再依赖容器,编
写更加容易。Spring 负责管理所有的Java Bean 组件,同样支持声明式的事务管理。我们只需要编写好Java Bean 组件,然后将它们"装配"起来就可以了,组件的初始化和管理均由Spring 完成,只需在配置文件中声明即可。这种方式最大的优点是各组件的耦合极为松散,并且无需我们自己实现Singleton 模式。
    缺点:多个spring 项目中,bean factory 不好做共享啊。硬伤!spring 的致命缺陷是不支持分布式应用,也就是重量级的ejb 容器能够存在的意义。1. 中断了应用程序的逻辑,使代码变得不完整,不直观。此时单从Source 无法完全把握应用的所有行为。2. 将原本应该代码化的逻辑配置化,增加了出错的机会以及额外的负担。3. 时光倒退,失去了IDE 的支持。在目前IDE 功能日益强大的时代,以往代码重构等让人头痛的举动越来越容易。而且IDE 还提供了诸多强大的辅助功能,使得编程的门槛降低很多。通常来说,维护代码要比维护配置文件,或者配置文件+代码的混合体要容易的多。4. 调试阶段不直观,后期的bug 对应阶段,不容易判断问题所在。

猜你喜欢

转载自blog.csdn.net/Juwenzhe_HEBUT/article/details/78399637