超细面试(妖魔鬼怪无处遁形,面试用时一个半小时)

Posted 白杨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了超细面试(妖魔鬼怪无处遁形,面试用时一个半小时)相关的知识,希望对你有一定的参考价值。

  • 请画出线程的生命周期,并列出创建线程的方式

    线程的5种状态:新建(New),就绪(Runnable),运行(Running),阻塞(Blocked),死亡(Dead)
    
    创建方式:继承Thread  实现Runnable   实现Callable  使用Executors

    问题来了:
      1. sleep结束后进入什么状态?
       就绪状态
      2. Runnable和Callable的区别?
    > Runnable执行方法是run(),Callable是call()
    > 实现Runnable接口的任务线程无返回值;实现Callable接口的任务线程能返回执行结果
    > call方法可以抛出异常,run方法若有异常只能在内部消化
      3. FutureTask是什么
            FutureTask<Object> futureTask = new FutureTask<>(实现了Callable的类实例);//将任务放进FutureTask里
             Thread thread = new Thread(futureTask);
             thread.start();
       或:
             ExecutorService executorService=Executors.newCachedThreadPool();
             executorService.submit(futureTask);
             executorService.shutdown();

    一个FutureTask可以用来包装一个Callable或Runnable对象。因为FutureTask实现了Runnable接口,一个FutureTask可以被提交给一个Executor来执行。
      4. Executors创建的几种线程池? ThreadPoolExecutor的参数?

       >
    newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
    > newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
    > newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
    > newSingleThreadExecutor 创建一个单线程化的线程池执行任务。

    public ThreadPoolExecutor (int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,BlockingQueue<Runnable> workQueue)
    
    

               > corePoolSize:线程池中所保存的核心线程数,包括空闲线程。

               > maximumPoolSize:池中允许的最大线程数。

               > keepAliveTime:线程池中的空闲线程所能持续的最长时间。

               > unit:持续时间的单位。

               > workQueue:任务执行前保存任务的队列,仅保存由execute方法提交的Runnable任务。


      
      

     

  • 请描述Synchuronized关键字,列出他常用锁。 请描叙一下Volatile和Synchronized的区别。
      Java 虚拟机中的同步(Synchronization)基于进入和退出管程(Monitor)对象实现
    
      ReentrantLock 

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

     

      问题延伸:

       ReentrantLock 和 Synchuronized有什么区别?

     

     

  • spring中bean的生命周期和作用域

        

  

 

  spring的controller默认是单例的,不要使用非静态的成员变量,否则会发生数据逻辑混乱。
  正因为单例所以不是线程安全的。

    解决方法:

    1、不要在controller中定义成员变量。
    2、万一必须要定义一个非静态成员变量时候,则通过注解@Scope(“prototype”),将其设置为多例模式。
    3、在Controller中使用ThreadLocal变量

 

  •   spring注解@Autowired,@Resource,@Qualifier
    @Autowired采取的策略为按照类型注入(ByType)。
      public class UserService {
        @Autowired
        private UserDao userDao; 
    }

    当一个类型有多个bean值的时候,会造成无法选择具体注入哪一个的情况,这个时候我们需要配合着@Qualifier使用。@Qualifier告诉spring具体去装配哪个对象。
    public class UserService {
        @Autowired
        @Qualifier(name="userDao1")    
        private UserDao userDao; 
    }

    @Resource默认按照ByName自动注入。
    public class UserService {
        @Resource  
        private UserDao userDao; 
        @Resource(name="studentDao")  
        private StudentDao studentDao; 
        @Resource(type="TeacherDao")  
        private TeacherDao teacherDao; 
        @Resource(name="manDao",type="ManDao")  
        private ManDao manDao; 
    } 

      ①如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。

      ②如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。

      ③如果指定了type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。

      ④如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。



     

  • 什么是事务?并发事务会引发什么问题? 列出事务隔离级别
    事务:是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合。
    问题:
      脏读。 (一个事务对数据进行了修改还未提交,另一个事务就使用了这个数据)
    修改丢失。 (两个事务同时在访问一个数据,两个事务先后都对其进行了修改,先修改的数据丢失)
    幻读。 (一个事务多次读同一数据,另一事务在这个数据中插入了一些数据,事务一再读时,好像出现了幻觉)
    不可重复读。(一个事务多次读同一数据,另一事务修改了这个数据,重复读取得内容不同。)
      不可重复读的重点是修改比如多次读取一条记录发现其中某些列的值被修改,幻读的重点在于新增或者删除比如多次读取一条记录发现记录增多或减少了。
    事务隔离级别:

               Read uncommitted 读未提交:就是一个事务可以读取另一个未提交事务的数据。

               Read committed 读提交:就是一个事务要等另一个事务提交后才能读取数据。

               Repeatable read 重复读:就是在开始读取数据(事务开启)时,不再允许修改操作

               Serializable 序列化 是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。


    问题延伸: 1.aop实现全局事务 2.aop的底层: 动态代理 3.spring提供了哪几种动态代理?区别。
    jdk cglib
    区别:JDK代理只能对实现接口的类生成代理;CGlib是针对类实现代理,对指定的类生成一个子类,并覆盖其中的方法,这种通过继承类的实现方式,不能代理final修饰的类。
    4.@Transaction的默认传播行为
    required 5.一个用@Transaction的方法调用另一个用了@Transaction的方法,执行几个事务

             不同类之间的方法调用,如类A的方法a()调用类B的方法b(),这种情况事务是正常起作用的。只要方法a()或b()配置了事务,运行中就会开启事务,产生代理。若两个方法都配置了事务,两个事务具体以何种方式传播,取决于设置的事务传播特性。

     同一个类内方法调用:重点来了,同一个类内的方法调用就没那么简单了,假定类A的方法a()调用方法b(),同一类内方法调用,无论被调用的b()方法是否配置了事务,此事务在被调用时都将不生效。
        6.try catch包裹是否能让transaction注解无效(差不多这个意思)
       会无效。解决方法: 在catch中抛出异常,
    但这里有个小细节:@Transactional不做任何配置 默认是对抛出的unchecked异常回滚,checked异常不会回滚,为了让所有异常都会让事务启动可以将 @Transactional配置为 @Transactional(rollbackFor = Exception.class)


     

  • JVM内存模型,并描叙各自的作用
  • 快速排序 
  • 手写单例模式并调优
  • 设计秒杀系统的架构图
  • redis的持久化RDB和AOF
  • Hashmap底层和1.8之后的改变,什么是红黑树。

以上是关于超细面试(妖魔鬼怪无处遁形,面试用时一个半小时)的主要内容,如果未能解决你的问题,请参考以下文章

阿里面试居然跟我扯了半小时的CyclicBarrier

阿里面试居然跟我扯了半小时的CyclicBarrier

面试官想到,一个Volatile,敖丙都能吹半小时

宁可多花1000元租房,也绝不要去挤半小时地铁

高并发系统设计,我和面试官扯了一个半小时!

Java线程池,这篇能让你和面试官聊了半小时