Java面经1

MVC的理解

MVC是Model—View—Controler的简称。即模型一视图一控制器。MVC是一种设计模式,它强制性的把应用程序的输入、处理和输出分开。

MVC中的模型、视图、控制器分别担负着不同的任务。

  • 视图:视图是用户看到并与之交互的界面。视图向用户显示相关的数据,并接受用户的输入。视图不进行任何业务逻辑处理。

  • 模型:模型表示业务数据和业务处理。相当于JavaBean。一个模型能为多个视图提供数据。这提高了应用程序的重用性。控制器:当用户单击Web页面中的提交按钮时,控制器接受请求并调用相应的模型去处理请求,然后根据处理的结果调用相应的视图来显示处理的结果。

  • 控制器:当用户单击页面中的提交按钮时,控制器接受请求并调用相应的模型去处理请求,然后根据处理的结果调用相应的视图来显示处理的结果。

MVC的处理过程:首先控制器接受用户的请求,调用相应的模型来进行业务处理,并返回数据给控制器.控制器调用相应的视图来显示处理的结果,并通过视图呈现给用户。

抽象类和接口的区别

  1. 接口可以被多重implements,抽象类只能被单一extends

  2. 接口只有定义,抽象类可以有定义和实现

  3. 接口的字段定义默认为:public static final, 抽象类字段默认是"friendly"(本包可见)

Hashtable、HashMap

HashTable的原理:通过节点的关键码确定节点的存储位置,即给定节点的关键码k,通过一定的函数关系H(散列函数),得到函数值H(k),将此值解释为该节点的存储地址。 HashMap与Hashtable很相似,但HashMap是非同步(unsynchronizded)和可以以null为关键码的。

JDK和JRE有什么区别?

JRE:Java Runtime Environment( java 运行时环境)。即java程序的运行时环境,包含了 java 虚拟机,java基础类库。

JDK:Java Development Kit( java 开发工具包)。即java语言编写的程序所需的开发工具包。JDK 包含了 JRE,同时还包括 java 源码的编译器 javac、监控工具 jconsole、分析工具 jvisualvm等。

==和equals的区别是什么?

== 是关系运算符,equals() 是方法,结果都返回布尔值

Object 的 == 和 equals() 比较的都是地址,作用相同

== 作用:

  • 基本类型,比较值是否相等

  • 引用类型,比较内存地址值是否相等

  • 不能比较没有父子关系的两个对象

equals()方法的作用:

  • JDK 中的类一般已经重写了 equals(),比较的是内容

  • 自定义类如果没有重写 equals(),将调用父类(默认 Object 类)的 equals() 方法,Object 的 equals() 比较使用了 this == obj

  • 可以按照需求逻辑,重写对象的 equals() 方法(重写 equals 方法,一般须重写 hashCode 方法)

static关键字和final关键字的区别

  • final的意思就是最终、最后的意思 final可以用来修饰类、方法、变量

    • 修饰类的时候表示该类不可变,不可继承,比如String

    • 修饰方法的时候表示该方法不可重写,比如模板方法

    • 修饰变量,表示该变量修饰之后变成常量

  • finally:finally作为异常处理的一部分,它只能用在try/catch语句中,并且附带一个语句块,表示这段语句最终一定会被执行(不管有没有抛出异常),经常被用在需要释放资源的情况下。

  • finalize:每一个对象都有这么个方法。这个方法在gc启动,该对象被回收的时候被调用。

  • static 表示全局 or 静态 static可以修饰方法,变量,代码块 在JVM中,被static修饰的方法和变量都存在方法区,他属于全局共享,而不是某个线程私有的

synchronized 关键字和 volatile 关键字的区别

  • volatile关键字是线程同步的轻量级实现,所以volatile性能肯定比synchronized关键字要好。但是volatile关键字只能用于变量⽽synchronized关键字可以修饰方法以及代码块。

  • 多线程访问volatile关键字不会发生阻塞,而synchronized关键字可能会发生阻塞

  • volatile关键字能保证数据的可见性,但不能保证数据的原子性。synchronized关键字两者都能保证。

  • volatile关键字主要用于解决变量在多个线程之间的可见性,而 synchronized关键字解决的是多个线程之间访问资源的同步性。

synchronized 和 Lock、ReentrantLock有什么区别

synchronized 与Lock的区别

  • synchronized 可以给类、方法、代码块加锁;而 lock 只能给代码块加锁。

  • synchronized 不需要手动获取锁和释放锁,使用简单,发生异常会自动释放锁,不会造成死锁;而 lock 需要自己加锁和释放锁,如果使用不当没有 unLock()去释放锁就会造成死锁,所以常在finally代码块释放。

  • 通过 Lock 可以知道有没有成功获取锁,而 synchronized 却无法办到。

synchronized 早期的实现比较低效,对比 ReentrantLock,大多数场景性能都相差较大,但是在 Java 6 中对 synchronized 进行了非常多的改进。

主要区别如下:

  • ReentrantLock 使用起来比较灵活,但是必须有释放锁的配合动作。

  • ReentrantLock 必须手动获取与释放锁,而 synchronized 不需要手动释放和开启锁。

  • ReentrantLock 只适用于代码块锁,而 synchronized 可用于修饰方法、代码块等。

① 两者都是可重入锁

两者都是可重入锁。“可重⼊锁”概念是:自己可以再次获取自己的内部锁。⽐如一个线程获得了某个对象的锁,此时这个对象锁还没有释放,当其再次想要获取这个对象的锁的时候还是可以获取的,如果不可锁重⼊的话,就会造成死锁。同一个线程每次获取锁,锁的计数器都自增1,所以要等到锁的计数器下降为0时才能释放锁。

② synchronized依赖于JVM而ReentrantLock依赖于API

③ ReentrantLock比synchronized增加了一些高级功能 主要有三个高级功能:1、等待可中断;2、可实现公平锁(先等待的线程先获得锁);3、可实现选择性通知(锁可以绑定多个条件)

④ 性能已不是选择标准

sychronized锁升级过程

  • 1.5前 synchronized之前一直都是重量级的锁,但是后来java官方是对他进行过升级的,他现在采用的是锁升级的方式去做的。

  • 1.6后 synchronized 获取锁的方式,JVM 使用了锁升级的优化方式,就是先使用偏向锁优先同一线程然后再次获取锁,如果失败,就升级为 CAS 轻量级锁,如果失败就会短暂自旋,防止线程被系统挂起。最后如果以上都失败就升级为重量级锁。

BIO、NIO、AIO区别有哪些?项目中有用到吗?Netty了解吗?

  • BIO、NIO、AIO BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。在活动连接数不是特别高(小于单机 1000)的情况下,这种模型是比较不错的,可以让每一个连接专注于自己的 I/O 并且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效的 I/O 处理模型来应对更高的并发量。

    NIO:New IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。NIO 是一种同步非阻塞的 I/O 模型,在Java 1.4 中引入了NIO框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。NIO中的N可以理解为Non-blocking,不单纯是New。它支持面向缓冲的,基于通道的I/O操作方法。NIO提供了与传统BIO模型中的 Socket 和 ServerSocket 相对应的 SocketChannel 和ServerSocketChannel 两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可以使用同步阻塞I/O来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发。

    AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO的操作基于事件和回调机制。也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。AIO 是异步IO的缩写,虽然 NIO在网络操作中,提供了非阻塞的方法,但是 NIO 的 IO 行为还是同步的。对于 NIO 来说,我们的业务线程是在 IO 操作准备好时,得到通知,接着就由这个线程自行进行 IO 操作,IO操作本身是同步的。查阅网上相关资料,我发现就目前来说 AIO 的应用还不是很广泛,Netty 之前也尝试使用过 AIO,不过又放弃了。

  • Netty 是一个 NIO 客户端服务器框架,可快速轻松地开发网络应用程序,例如协议服务器和客户端。它极大地简化和简化了网络编程,例如 TCP 和 UDP 套接字服务器。

    • 执行流程 image text

    • Netty 核心组件

      • Channel ​ Channel是 Java NIO 的一个基本构造。可以看作是传入或传出数据的载体。因此,它可以被打开或关闭,连接或者断开连接。

      • EventLoop 与 EventLoopGroup ​ EventLoop 定义了Netty的核心抽象,用来处理连接的生命周期中所发生的事件,在内部,将会为每个Channel分配一个EventLoop。 EventLoopGroup 是一个 EventLoop 池,包含很多的 EventLoop。 Netty 为每个 Channel 分配了一个 EventLoop,用于处理用户连接请求、对用户请求的处理等所有事件。EventLoop 本身只是一个线程驱动,在其生命周期内只会绑定一个线程,让该线程处理一个 Channel 的所有 IO 事件。 一个 Channel 一旦与一个 EventLoop 相绑定,那么在 Channel 的整个生命周期内是不能改变的。一个 EventLoop 可以与多个 Channel 绑定。即 Channel 与 EventLoop 的关系是 n:1,而 EventLoop 与线程的关系是 1:1。

      • ServerBootstrapBootstrap ​ Bootstarp 和 ServerBootstrap 被称为引导类,指对应用程序进行配置,并使他运行起来的过程。Netty处理引导的方式是使你的应用程序和网络层相隔离。 ​ Bootstrap 是客户端的引导类,Bootstrap 在调用 bind()(连接UDP)和 connect()(连接TCP)方法时,会新创建一个 Channel,仅创建一个单独的、没有父 Channel 的 Channel 来实现所有的网络交换。 ​ ServerBootstrap 是服务端的引导类,ServerBootstarp 在调用 bind() 方法时会创建一个 ServerChannel 来接受来自客户端的连接,并且该 ServerChannel 管理了多个子 Channel 用于同客户端之间的通信。

      • ChannelHandlerChannelPipeline ChannelHandler 是对 Channel 中数据的处理器,这些处理器可以是系统本身定义好的编解码器,也可以是用户自定义的。这些处理器会被统一添加到一个 ChannelPipeline 的对象中,然后按照添加的顺序对 Channel 中的数据进行依次处理。

      • ChannelFuture Netty 中所有的 I/O 操作都是异步的,即操作不会立即得到返回结果,所以 Netty 中定义了一个 ChannelFuture 对象作为这个异步操作的“代言人”,表示异步操作本身。如果想获取到该异步操作的返回值,可以通过该异步操作对象的addListener() 方法为该异步操作添加监 NIO 网络编程框架 Netty 听器,为其注册回调:当结果出来后马上调用执行。 ​ Netty 的异步编程模型都是建立在 Future 与回调概念之上的。

HashMap和HashTable的区别是什么?

线程是否安全: HashMap 是非线程安全的,HashTable 是线程安全的;HashTable 内部的方法基本都经过 synchronized 修饰。(如果你要保证线程安全的话就使用 ConcurrentHashMap吧!);

效率: 因为线程安全的问题,HashMap 要比 HashTable 效率⾼一点。另外,HashTable 基本被淘汰,不要在代码中使用它;

对Null key和Null value的支持: HashMap 中,null 可以作为键,这样的键只有一个,可以有一个或多个键所对应的值为 null。但是在 HashTable 中 put 进的键值只要有一个 null,直接抛出 NullPointerException。 这是因为HashTable是使用的是安全失败机制(fail-safe),这种机制会使你此次读到的数据不一定是最新的数据。 如果你使用null值,就会适得其无法判断对应的key是不存在还是为空,因为你无法在调用一次contain(key)来对key是否存在进行判断。

底层数据结构: JDK1.8 以后的 HashMap 在解决哈希冲突时有较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红⿊树,以减少搜索时间。Hashtable 没有这样的机制。

HashMap和HashSet的区别?HashSet是如何检查重复的?

  • HashSet 底层就是基于 HashMap 实现的。 hashmap是实现了map接口,hashset实现了set接口。 存储键值对,存储对象,

  • hashmap用put向map中添加元素,hashset调用add向set中添加元素。

  • hashset如何检查重复: 当你把对象加⼊ HashSet 时,HashSet会先计算对象的 hashcode 值来判断对象加⼊的位置,同时也会与其他加⼊的对象的hashcode值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同hashcode值的对象,这时会调用 equals()方法来检查hashcode相等的对象是否真的相同。如果两者相同,HashSet就不会让加⼊操作成功。

Object类下有哪些方法?

  • clone方法 保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常。

  • getClass方法 final方法,获得运行时类型。

  • toString方法 该方法用得比较多,一般子类都有覆盖。

  • equals方法 该方法是非常重要的一个方法。一般equals和==是不一样的,但是在Object中两者是一样的。子类一般都要重写这个方法。

  • hashCode方法 该方法用于哈希查找,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。

  • wait方法 wait方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。

  • notify方法 该方法唤醒在该对象上等待的某个线程。

  • notifyAll方法 该方法唤醒在该对象上等待的所有线程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值