面试题、三

每日面试题

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

 

猜你喜欢

转载自www.cnblogs.com/zhaozhitong/p/12450105.html