自己面试总结

自己面试总结,第1张

1.springMvc 中的aop和ioc
  • AOP: Aop是OOP的补充,面向对象编程会造成大量重复的且与对象核心功能不相关的代码,aop采用“横切”的思想,剖开封装对象的内部,并将那些与业务无关,却被业务模块所共同调用的代码封装起来,以便减少系统的重复代码。
  • IOC: 控制反转,有Ioc容器之前,我们需要什么对象就会创建或直接调用已存在的对象,如,当A需要B时,要么创建B对象,要么调用已经存在的B对象,此时A依赖B,有Ioc容器之后,创建B对象的时机交给了IOC容器,当A需要B时,Ioc会主动创建B对象注入到A需要的地方。A获取依赖对象B的过程由主动变成了被动,控制键发生了翻转,这就是控制反转。
2.springMvc执行原理

用户发送http请求到DispatcherServlet前端控制器,让后调用HandlerMapping找到合适的适配器给前端,在调用HandlerAdepter处理器适配器进行处理,此时相当于进入Controller层,返回一个ModelAndView对象给DispatcherServlet,让后调用视图解析器viewresolver进行解析,返回view视图,前端控制器进行渲染返回给用户

3.常见的设计模式
  • 单例模式:保证一个类仅有一个实例,并提供一个全局访问点,比如一些配置文件,或者管理类可以设置为单例,我们常用的线程池也是单例的
  • 工厂模式:创建对象需要大量的重复代码时,通过子类实现方法来创建对象。如spring中通过工厂模式将创建对象的任务交给容器管理。
4.springbean的生命周期,以及AOP发生在其中那个阶段

       生命周期: 实例化——属性赋值——初始化——销毁

        Aop发生在初始化的阶段

5.synchronized锁升级

        synchronized修饰方法,锁定的就是调用这个同步方法的对象;修饰代码块时,锁对象本身;

修饰静态方法,如果是括号内有类,则锁这个类对象,如果直接在静态方法上,则锁本身的类。

  • 无锁:当一个对象被创建之后,还没有线程进入,这个时候对象处于无锁状态
  • 偏向锁:偏向锁的获取方式是把对象头的MarkWord部分标记上线程ID,以表示哪一个线程获得了偏向锁。具体是:先读取对象的MarkWord,判断是否处于可偏向状态,如果是,则用CAS *** 作,把自己的线程ID写入MarkWord,如果不是已偏向状态,则检测MarkWord中存储的线程ID是否是当前ID,是就执行同步代码块,不是就撤销偏向锁
  • 轻量级锁:竞争锁的线程首先要拷贝对象头中的MarkWord到栈针的锁记录中。拷贝成功后使用CAS *** 作尝试将对象的MarkWord更新为指向当前线程的指针,如果更新成功,那么这个线程就拥有该对象的锁,如果失败,则意味着有多个线程在竞争。当竞争线程尝试占用轻量级锁多次失败后,会膨胀成重量级锁,重量级线程指针指向竞争线程,竞争线程也会阻塞,等待轻量级线程释放锁池后也会唤醒
  • 重量级锁:

    当线程没有获得轻量级锁时,线程会CAS自旋来获取锁,当一个线程自旋10次之后,仍然未获得锁,那么就会升级成为重量级锁。成为重量级锁之后,线程会进入阻塞队列(EntryList),线程不再自旋获取锁,而是由CPU进行调度,线程串行执行。

补充:

        自旋锁:某线程需要获取锁,但是该锁已经被其他线程占用了,该线程不会被挂起,而是不断消耗CPU的时间,不停地试图获取锁。

        可重入锁:指一个线程在外层方法获取锁时候,在进入内层方法会自动获取锁,Reentrantlock好处是避免死锁。就比如人排队挑水一样,想让每人的每个桶都装满水,就要给这个人和他的桶都上锁,接满再让下一个人来。

6.nio aio bio的区别(网络的问题)

BIO是一个连接一个线程。
NIO是一个请求一个线程。
AIO是一个有效请求一个线程。

  • BIO:同步阻塞IO模式,数据的读写必须阻塞在一个线程内,等待其完成
  • NIO:同时支持阻塞和非阻塞模式
  • AIO:异步非阻塞IO模型

以烧开水为例,BIO就是安排一个线程在水壶旁边知道这个水烧开,再去烧下一个。NIO是叫一个线程不断询问每个水壶的状态是否发生改变,在进行下一步,AIO是给水壶装上开关,水烧开自动通知。

7.java类加载机制以及加载过程

         JVM启动之后,java开始使用三中类型的类加载器:

                启动类加载器:加载核心类

                扩展类加载器:加载JRE扩展目录

                应用加载器:默认自己实现的类加载器都是此应用类加载器的自家在其,父类是扩展类加载器

类加载的双亲委派机制:JVM加载类时默认采用双亲委派机制,也就是某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,因此,所有的加载请求最终都应该传到顶层的启动类加载器中。如果父类加载器可以完成这个类加载请求,就成功返回;只有当父类加在其无法完成此请求时,子加载器才会尝试自己加载。

类加载过程:

也可以说是   加载——连接——初始化

类加载的过程指的是JVM虚拟机把.class文件中类信息加载进内存,并进行解析生成对应的class对象的过程。

8.HashMap取数据三种方法

 public static void main(String[] args) {
        HashMap map = new HashMap<>();
        map.put("1", "aa");
        map.put("2", "aa");
        map.put("3", "cc");
        map.put("2", "bb");
 
        //HashMap 取数据几种方法
        //1.取key再找。因为key是唯一,则用Set集合来存key
        Set set = map.keySet();
        Iterator it = set.iterator();
        while(it.hasNext()){
            String key = it.next();
            String value = map.get(key);
            System.out.println(key + ":" + value);
        }
 
        System.out.println("------");
        //2.把整个映射取出来,整个映射类型是EntrySet 即Set,每个映射类型是Entry
        Set> entrySet = map.entrySet();
        Iterator> entryit = entrySet.iterator();
        Map.Entry entry;
        while(entryit.hasNext()){
            entry = entryit.next();
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + ":" + value);
        }
 
        System.out.println("------");
        //3.把值的集合取出来,因为key唯一,值不唯一,所以所有值集合是Collection
        Collection values = map.values();
        Iterator vit = values.iterator();
        while (vit.hasNext()) {
            String value = vit.next();
            System.out.println(value);
        }
    }

借用代码做一个总结:1.用map.keySet获取所有key的集合,让后遍历,根据key获取v

2.获取所有KV键值对,遍历,用getkey,getvalue获取k,v值

3.不常用,不总结了,哈哈哈

9.file类常用方法
  • createNewFile()在指定位置创建一个空文件
  • mkdir()  在指定位置创建一个单级文件夹
  • mkdirs()  在指定位置创建一个多级文件夹。
  • exists()  文件或文件夹是否存在。
  • isFile()  是否是一个文件,如果不存在,则始终为false。
  • getName()  获取文件或文件夹的名称,不包含上级路径。
  • getPath()返回该file的路径。
10.synchronized和lock有什么区别

        lock是一个接口,synchronized是Java的一个关键字。synchronized发生异常时会自己动释放占有锁,因此不会出现死锁,lock发生异常时需要手动释放锁,否则会引起死锁发生。

11.线程池的优势

        #使用线程池可以减少创建和销毁线程的次数,使每个工作的线程都可以重复使用

        #可以根据系统的承受能力,调整线程池中工作线程的数量,防止因为消耗过多内存导致服务器崩溃

12.AOP代理模式

静态代理:创建对象并对代理对象的功能调用并增强

Jdk动态代理:使用反射机制,动态创建代理类对象,实现InvocationHandler接口,调用目标对象的方法,并做功能增强。

13.JVM堆内存结构

        java堆分为年轻代和老年代,年轻代又分为伊甸园(Eden)和幸存区(Survior),幸存区又分为From Surrivior空间和To Surrivior空间。年轻代存储“新生对象”,我们新创建的对象存储在年轻代中,当年轻代内存中占满后,会触发MinorGc,清理年轻代中存储的对象,经过多次Gc后仍然存活的对象会移动到老年代中进行存储。老年代空间占满后会触发Full GC

14.http和tcp有什么区别
  • http是一个简单的请求-响应协议。TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。
  • TCP连接到不同但互连的计算机通信网络的主计算机中的成对进程之间依靠TCP提供可靠的通信服务。http通常运行在TCP之上
  • HTTP超文本传输协议,是应用层的协议,以TCP为基础
    TCP:传输控制协议,是传输层的协议,以IP协议为基础
  • Http是无转态的连接,TCP是有状态的长连接
15.抽象类和接口的区别

 # 接口能定义抽象方法,但不能实现,抽象类既能定义也能实现方法

 # 抽象类要被子类继承,接口要被类实现。

# 单继承多实现,抽象类只能单继承,接口可以被多个实现

# 接口强调功能,抽象类是所属关系

16.集合

 17.UDP/TCP以及相应的使用场景  
  • TCP面向连接(先建立连接才能传输数据)。

        提供可靠的服务,通过TCP连接传输的数据,无差错,不丢失,不重复,且按序到达。
        传输效率较低。
        TCP的连接只能是点到点,一对一的。

  • Udp面向无连接,发送数据之前不需要建立连接。

        尽最大努力交付,即不保证可靠交付。
        传输效率高,适用于对高速传输和实时性有较高的通信或广播通信。
        支持一对一,一对多,多对一和多对多的交互通信
        

 TCP应用场景:浏览器http,qq传输文件
 UDP:qq语音,qq视频

18.线程有那些状态?

新建状态:生成线程对象,并没有调用start方法时,该线程处于创建状态
就绪状态:线程调用了start方法之后,该线程就进入了就绪状态,但是此时线程调用程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。(准备开始争抢CPU时间片。)
运行状态:线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数中的代码(抢到了CPU时间片)
阻塞状态:线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如某项资源就绪)之后再继续运行。sleep,suspend,wait等方法都可以导致线程阻塞。
死亡状态:如果一个线程的run方法执行结束或者调用stop方法之后,该线程就会死亡。对于已经死亡的线程,无法在使用start方法令其进入就绪状态

19.sleep()和wait()有什么区别?

        sleep是Thread的静态方法,让调用线程进入睡眠状态,让出执行机会给其他线程,等休眠结束之后会继续争抢CPU时间片。因为sleep是静态方法,不能改变对象的机锁,当一个synchronized块中调用了sleep() 方法,线程虽然进入休眠,但是对象的机锁没有被释放,其他线程依然无法访问这个对象。
        Wait是object类的方法,当一个线程执行到wait方法时,它就进入到一个与该对象相关的等待池,同时释放对象机锁,使得其他线程能够访问,可以通过notify,notifyAll方法来唤醒等待的线程。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/904841.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-15
下一篇 2022-05-15

发表评论

登录后才能评论

评论列表(0条)

保存