面试问题总结

基础篇

1、谈谈多态,及多态的好处

多态,父类引用指向子类。

当把不同的子类对象都当做父类类型来看待,可以屏蔽不同子类对象之间的实现差异,从而写出通用的代码达到通用编程,以适应需求的不断变化。

在实际开发中,父类类型作为方法形式参数,传递子类对象给方法,进行方法的调用,更能体现出多态的拓展性和便利

方便代码维护和拓展

2、谈谈继承,继承得好处

从上层往下层看,当定义类B时,如果类A有和B相同的内容,且A和B属于同一类型,这是B就可继承自A

从下层往上层看,当定义的多个类属于同一类型,且有相同的内容,可以向上抽取出一个类,这便形成了继承关系

继承得好处:

简化了人们对事物的认识和描述,能清晰体现相关类间的层次结构关系;

能清晰体现相关类间的层次结构关系;继承提供了软件复用功能。这种做法能减小代码和数据的冗余度,大大增加程序的重用

性;提供多重继承机制;

大大增加了程序的易维护性。

3、为什么用封装

简化代码,方便复用,在实现一个功能的时候只需要关注结果,而不需要关注里面做了什么(隐藏信息,实现细节 )。

4、讲讲protect在java中的作用,什么时候用它

protected修饰的变量或方法只能被当前类,同包类或者子孙类继承或使用

一般情况下为了实现纯粹的封装用的就是private,而使用protected可以封装也可以继承

当一些类,需要继承,但是不想公开的时候可以用protect

5、串行、并行和并发

       顺序执行:你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行。

  并发:你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。

  并行:你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。

 

并发,指的是多个事情,在同一时间段内同时发生了。  
并行,指的是多个事情,在同一时间点上同时发生了。

6、设计模式(单例)

单例:就是整个程序有且仅有一个实例。该类负责创建自己的对象,同时确保只有一个对象被创建。

懒汉模式,饿汉模式,双重锁机制,单例模式一般用的比较多,双重锁的话是处理多线程任务时,使用的一种机制。

懒汉模式:线程不安全,延迟初始化

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
  
    public static 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;  
    }  
}

双重锁机制:线程安全,延迟初始化。这种方式采用双锁机制,安全且在多线程情况下能保持高性能。 

(注意volatile关键字)

public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
}

双重检查模式,进行了两次的判断,第一次是为了避免不要的实例,第二次是为了进行同步,避免多线程问题。由于singleton=new Singleton()对象的创建在JVM中可能会进行重排序,在多线程访问下存在风险,使用volatile修饰signleton实例变量有效,解决该问题 

静态内部类单例模式

public class Singleton { 
    private Singleton(){
    }
      public static Singleton getInstance(){  
        return Inner.instance;  
    }  
    private static class Inner {  
        private static final Singleton instance = new Singleton();  
    }  
}

只有第一次调用getInstance方法时,虚拟机才加载 Inner 并初始化instance ,只有一个线程可以获得对象的初始化锁,其他线程无法进行初始化,保证对象的唯一性。目前此方式是所有单例模式中最推荐的模式,但具体还是根据项目选择。

枚举(扩展):默认枚举实例的创建是线程安全的,并且在任何情况下都是单例。

public enum Singleton  {
    INSTANCE 
 
    //doSomething 该实例支持的行为
      
    //可以省略此方法,通过Singleton.INSTANCE进行操作
    public static Singleton getInstance() {
        return Singleton.INSTANCE;
    }
}
  • 枚举类隐藏了私有的构造器。
  • 枚举类的域 是相应类型的一个实例对象
  • 枚举的单例生产中使用较少,主要是太简单以致可读性差

6、设计模式(装饰者设计模式(动态代理))

 

 

7、[a,b,c]、[a,b]、[a]三个索引哪一个搜的快,为什么

 

8、讲讲hashMap

hashMap键唯一,值可以不唯一。键是set集合,set集合保证键唯一的方法是,如果存的键是空,则默认为0,否则进行hash值比较,如果hash值相同,则在在键后跟链表(处理hash冲突),当达到8时链表转换成红黑树(jdk1.8之后)。

 //判断键值是否为空,是则默认为0 
static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

 

9、讲讲红黑树

 

 

10、讲讲GC

 

11、servlet生命周期

首先加载servlet的class,实例化servlet,然后初始化servlet调用init()的方法,接着调用服务的service的方法处理doGet和doPost方法,最后是我的还有容器关闭时候调用destroy 销毁方法。

12、jsp和servlet的区别

jsp本质就是servlet,Jsp是Servlet的一种简化,使用Jsp只需要完成程序员需要输出到客户端的内容,Jsp中的Java脚本如何镶嵌到一个类中,由Jsp容器完成。

但jsp内有内置对象,servlet没有,

jsp更擅长表现于页面显示,servlet更擅长于逻辑控制.

13、讲讲对事物的理解

 

14、讲讲ThreadLocal

 

15、StringBuilder、StringBuffer、String的区别

 

16、http和tcp的区别

 

17、post请求,和get请求的区别

 

技术篇

1、springboot定时器的配置

1、在启动类中加入定时器的注解@EnableScheduling来注册定时任务

2、在定时任务的方法上加上@Scheduled(cron = "0/30 * * * * ?") 并在里面写cron表达式

2、springboot定时器的配置多线程任务

配置一个配置类ScheduleConfig实现SchedulingConfigurer接口,并重写里面的方法,设定定时任务池,来实现多线程的计时任务

下面这篇博文写的很好,可以参考 

https://blog.csdn.net/u013456370/article/details/79411952 

3、spingboot 定时器搭建集群的话怎么设置 (百度面试的)

 

4、springcloud运行过程中如果一台服务处故障了,这时候怎么处理

通常会搭建服务集群,如果一台服务宕机坏掉了,会Erake注册中心映射到另一台服务上。

5、springcloud的优点

 

6、springcloud的缺点

维护起来难(面试的马上就会问,怎么难了。。。。举个例子,我举你个鬼啊)

 

7、讲讲倒排索引

 

8、有三个索引【a,b,c】【a,b】【a】哪一个查的快,为什么

 

9、redis的五中数据类型,其中list里面一条数据中间出错了,能不能修改,能的话,怎么修改,不能的话为什么

 

10、讲讲缓存穿透,缓存击穿,缓存雪崩

缓存穿透:缓存中和数据库中都没有数据,但是用户不停的连续发生这样的请求,这时的用户很可能是攻击者,攻击会导致数

据库压力过大

解决方案:将搜索信息和ip作为key,搜索次数作为value存进redis,设置缓存有效时间,一定时间内访问超过一定次数的话进行拦截。

缓存击穿:    缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力

解决方案:设置redis永久有效;设置互斥锁,当redis获取为空时,先获取锁,去数据库中取数据,并更新redis,如果更新成功则释放锁;而如果拿不到锁,证明服务正在想数据库中获取数据,此时线程休眠一定时间,知道拿到锁。

缓存雪崩:缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,        缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。

解决方案:

  1. 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
  2. 如果缓存数据库是分布式部署,将热点数据均匀分布在不同的缓存数据库中。
  3. 设置热点数据永远不过期

11、rabbitMQ 发送消息的时候,如果消息一斤发送出去,这个时候系统出了故障,rabbitmq返回一个错误,又重新发送了,用户收到了两份内容,请问如何避免

处理这样的问题尽量避开MQ的处理,因为MQ处理的话会,降低消息的吞吐量。尽量在应用层设置

收消息方,收到是1,没收到是0,还需要处理一下异常让他不进行二次发送。

12、rabbit发送两条消息,怎样保证发送顺序

在 MQ 层面支持消息的顺序处理开销太大,为了极少量的需求,增加整体上的复杂度得不偿失。所以,还是在应用层面处理比较好,或者业务逻辑进行处理。

应用层处理方法:

1:“同步执行”:当一个消息执行完之后,再发布下一个消息。

2、消息实体中增加:版本号 & 状态机 & msgid & parent_msgid,通过 parent_msgid 判断消息的顺序(需要全局存储,记录消息的执行状态)。

处理方式

13、讲讲集群

 

14、ES怎么存数据

使用ES,需要先创建相关的实体类,实体类上需要有相应的注解标明映射和类型

@Document(indexName = "skuinfo", type = "docs")

同时各个字段也要有响应注解说明是否创建索引,是否分词,采用什么分词器等等

存储数据时,需要先根据实体类创建相关索引和映射

 //创建索引

        elasticsearchTemplate.createIndex(SkuInfo.class);
        //创建映射
        elasticsearchTemplate.putMapping(SkuInfo.class);

在创建操作es的dao类,需要继承 ElasticsearchRepository并规定泛型

public interface SkuInfoDao extends ElasticsearchRepository<SkuInfo,Long> {
}

 然后直接利用里面封装的方法存数据

业务篇

1、讲讲购物车实现原理,如果购物车里面有8件商品,提交其中两件,问怎么操作

 

2、怎样实现秒杀,

 

编码篇

1、一个数组Integer array = {2,5,1,8080,3306,9200,3,5,5,2},计算里面出现最多的数字,如果出现相同次数的数字,返回最大的数字的次数,如上面数组中5出现3次。时间复杂度要尽可能的低,越低,分熟越高

这里可以用HashMap存储相关的值,达到一次遍历即得出结果,相关代码自己想。

 

2、一个student表,有No,name,class,score共计四个字段

问1:用一条sql语句得到及格人数大于30的班级

 

问2:用一条sql得到每个班及格人数和不及格人数

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章