• 面试题、三


    每日面试题

    2020-02-06

    1.进程和线程的区别

    一个程序下至少有一个进程,一个进程下至少有一个线程,一个进程下也可以有多个线程来增加程序的执行速度。

    2.线程的生命周期,多线程并发会有什么影响

    当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。 在线程的生命周期中,它要经过新建(New)、就绪(Runnable)、运行(Running)、阻塞 (Blocked)和死亡(Dead)5种状态。 多线程并发的影响:``多线程并发时会不安全,多线程同时操作对象的属性或者状态时,会因为线程之间的信息不同步,A线程读取到的状态已经过时,而A线程并不知道。

    3.队列和栈的特性。在什么实际案例中见过?

    堆栈的特性:先进后出,后进先出``队列的特性:先进先出,后进后出

    4.synchroized的作用,java中还有那些常用的锁?

    synchronized` `它可以把任意一个非 NULL 的对象当作锁。他属于独占式的悲观锁,同时属于可重入锁。
    1``. 作用于方法时,锁住的是对象的实例(``this``);
    2``. 当作用于静态方法时,锁住的是Class实例, 会锁所有调用该方法的线程;
    3``. ``synchronized` `作用于一个对象实例时,锁住的是所有以该对象为锁的代码块。
    Java中常见的锁还有乐观锁、悲观锁、自旋锁

    5.synchronized 和 volatile 的区别是什么?

    1``.``volatile``本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; ``synchronized``则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
    2``.``volatile``仅能使用在变量级别;``synchronized``则可以使用在变量、方法、和类级别的
    3``.``volatile``仅能实现变量的修改可见性,不能保证原子性;而``synchronized``则可以保证变量的修改可见性和原子性
    4``.``volatile``不会造成线程的阻塞;``synchronized``可能会造成线程的阻塞。
    5``.``volatile``标记的变量不会被编译器优化;``synchronized``标记的变量可以被编译器优化

    6.spring的Bean的作用域和生命周期

    Bean的作用域:单例(singleton)、原型(prototype)、请求(request)、会话(session)、全局会话(global session)
    Bean的生命周期流程:
    1``.首先容器启动后,会对scope为singleton且非懒加载的bean进行实例化,
    2``.按照Bean定义信息配置信息,注入所有的属性,
    3``.如果Bean实现了BeanNameAware接口,会回调该接口的setBeanName()方法,传入该Bean的id,此时该Bean就获得了自己在配置文件中的id,
    4``.如果Bean实现了BeanFactoryAware接口,会回调该接口的setBeanFactory()方法,传入该Bean的BeanFactory,这样该Bean就获得了自己所在的BeanFactory,
    5``.如果Bean实现了ApplicationContextAware接口,会回调该接口的setApplicationContext()方法,传入该Bean的ApplicationContext,这样该Bean就获得了自己所在的ApplicationContext,
    6``.如果有Bean实现了BeanPostProcessor接口,则会回调该接口的postProcessBeforeInitialzation()方法,
    7``.如果Bean实现了InitializingBean接口,则会回调该接口的afterPropertiesSet()方法,
    8``.如果Bean配置了init-method方法,则会执行init-method配置的方法,
    9``.如果有Bean实现了BeanPostProcessor接口,则会回调该接口的postProcessAfterInitialization()方法,
    10``.经过流程``9``之后,就可以正式使用该Bean了,对于scope为singleton的Bean,Spring的ioc容器中会缓存一份该bean的实例,而对于scope为prototype的Bean,
    ``每次被调用都会``new``一个新的对象,期生命周期就交给调用方管理了,不再是Spring容器进行管理了
    11``.容器关闭后,如果Bean实现了DisposableBean接口,则会回调该接口的destroy()方法,
    12``.如果Bean配置了destroy-method方法,则会执行destroy-method配置的方法,至此,整个Bean的生命周期结束。

    7.spring常用的六个注解以及作用

    @Component``(value)
    配置类,当使用该注解时,SpringIOC会将这个类自动扫描成一个bean实例
    不写的时候,默认是类名,且首字母小写
    @Autowired
    自动装配,会根据类型寻找指定的Bean,required:表示假如说在bean目录下找不到指定的注解还需不需要注入,默认是``true` `修改为``false``时,表示假如说没有找到可以允许不注入。
    @ImportResource``({``"classpath:xxx.xml"``})
    能够读取多个xml文件,这样就可以引入多个xml定义的bean
    @Service
    标注于业务层组件上表示定义一个bean,自动根据所标注的组件名称实例化一个首字母为小写的bean。
    @RequestBody
    用来传对象参数
    @Resource
    用来自动装配Bean,激活一个命名资源的依赖注入。``@Resource``属性name可以定义被自动装配Bean的名称

    8.解释什么是事务,多线程事务并发会产生哪些问题,简述事务的四种隔离性

    事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消。
    也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做。
    事务的结束有两种,当事务中的所以步骤全部成功执行时,事务提交。如果其中一个步骤失败,将发生回滚操作,撤消撤消之前到事务开始时的所以操作。
    并发问题可归纳为以下几类:
    A.丢失更新
    B.脏读
    C.不可重复读
    D. 覆盖更新
    E.虚读(幻读)
    事务的四种隔离性:
    A.Serializable(串行化):一个事务在执行过程中完全看不到其他事务对数据库所做的更新
    (事务执行的时候不允许别的事务并发执行。事务串行化执行,事务只能一个接着一个地执行,而不能并发执行。)。
    B.Repeatable Read(可重复读):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,但是不能看到其他其他事务对已有记录的更新。
    C.Read Commited(读已提交数据):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,而且能看到其他事务已经提交的对已有记录的更新。
    D.Read Uncommitted(读未提交数据):一个事务在执行过程中可以看到其他事务没有提交的新插入的记录,而且能看到其他事务没有提交的对已有记录的更新。

    9.什么是aop,spring的几种通知方式

    aop是面向切面编程,在整个系统中,动态横向添加新的功能还不改变原来的业务流程的编程
    spring的几种通知方式:
    1``.前置通知(方法调用前通知)
    2``.后置通知(方法调用后正常返回的时候通知,可以获取返回值,发生异常的时候不会执行)
    3``.最终通知(无论程序是否发生异常都会执行的)
    4``.异常通知(发生异常的执行)
    5``.环绕通知(方法执行的时候执行)

    10.画出jvm的内存运行图并解释其作用

    首先Java源代码文件(.java后缀)会被Java编译器编译为字节码文件(.``class``后缀),
    然后由JVM中的类加载器加载各个类的字节码文件,加载完毕之后,交由JVM执行引擎执行。
    在整个程序执行过程中,JVM会用一段空间来存储程序执行期间需要用到的数据和相关信息,
    这段空间一般被称作为Runtime Data Area(运行时数据区),也就是我们常说的JVM内存。
    因此,在Java中我们常常说到的内存管理就是针对这段空间进行管理

     

    11.手写快速排序算法

    StreamApi
    第一种排序:sorted(),自然排序
    @Test
    public void test8() {
      List list = Arrays.asList("aaa","bbb","ccc","ddd");
      list.stream().sorted().forEach(System.out::println);
    }
    第二种排序:sorted(Comparator com)-定制排序
    public void test8() {
      List list = Arrays.asList("qqq","aaa","bbb","ccc","ddd");
      list.stream().sorted().forEach(System.out::println);
      deptList.stream().sorted((x,y) -> {
        if(x.getDeptno().equals(y.getDeptno())) {
          return x.getDname().compareTo(y.getDname());
        }else {
          return x.getLoc().compareTo(y.getLoc());
        }
      });
    }
    // 第三种按Map排序
    //创建一个Map,并填入数据
    Map codes = new HashMap<>();
    codes.put("United States", 1);
    codes.put("Germany", 49);
    codes.put("France", 33);
    codes.put("China", 86);
    codes.put("Pakistan", 92);
    // 按照Map的键进行排序
    Map sortedMap = codes.entrySet().stream()
            .sorted(Map.Entry.comparingByKey())
            .collect(
            Collectors.toMap(
            Map.Entry::getKey,
            Map.Entry::getValue,
            (oldVal, newVal) -> oldVal,
            LinkedHashMap::``new
            )
            );
    // 将排序后的Map打印
    sortedMap.entrySet().forEach(System.out::println);
    //按照value排序
      Map sortedMap2 = codes.entrySet().stream()
                .sorted(Map.Entry.comparingByValue())
                .collect(Collectors.toMap(
                Map.Entry::getKey,
                Map.Entry::getValue,
                (oldVal, newVal) -> oldVal,
                LinkedHashMap::``new``));
    //排序以后打印
    
    sortedMap2.entrySet().forEach(System.out::println);
    

    12.手写线程安全的单例模式

    //懒汉式,线程安全
    public class Singleton { 
      private static Singleton instance; 
      private Singleton (){} 
      public static synchronized Singleton getInstance() { 
        if (instance == null) { 
          instance = new Singleton(); 
        } 
      return instance; 
      } 
    }
    
    //饿汉式
    public class Singleton { 
      private static Singleton instance = new Singleton(); 
      private Singleton (){} 
      public static Singleton getInstance() { 
        return instance; 
      } 
    } 
    
    //双检锁/双重校验锁(DCL,即double-checked locking),JDK1.5起
    public class Singleton { 
      private volatile static Singleton singleton; 
      private Singleton (){} 
      public staitic Singleton getSingleton() { 
      if (singleton == null) { 
        synchronized (Singleton.class) { 
          if (singleton == null) { 
            singleton = new Singleton(); 
          } 
        } 
      }
      return singleton; 
      } 
    }
    
    //登记式/静态内部类
    public class Singleton { 
      private static class SingletonHolder { 
      private static final Singleton INSTANCE = new Singleton(); 
      } 
      private Singleton (){} 
      public static final Singleton getInstance() { 
        return SingletonHolder.INSTANCE; 
      } 
    }
    
    //枚举,JDK1.5起
    public enum Singleton { 
      INSTANCE; 
      public void whateverMethod() { 
      } 
    }
    
    经验之谈:一般情况下,不建议使用懒汉方式,建议使用饿汉方式。只有在要明确实现lazy loading 效果时,才会
    使用登记方式。如果涉及到反序列化创建对象时,可以尝试使用枚举方式。如果有其他特殊的需求,可以考虑使用双检
    锁方式

    13.设计一个秒杀的结构图

    img

     

  • 相关阅读:
    每天拿出来2小时浪费(文/王路) 作者: 王路
    objective-c自学总结(二)---init/set/get方法
    objective-c自学总结(一)---面向对象
    水仙花数
    独木舟上的旅行
    阶乘之和
    小明的调查统计
    管闲事的小明
    重温《STL源码剖析》笔记 第一章
    重温《STL源码剖析》笔记 第三章
  • 原文地址:https://www.cnblogs.com/zhaozhitong/p/12450105.html
Copyright © 2020-2023  润新知