Java开发工程师常见面试题(长期更新)

Redis:

1、Redis常见的五种数据类型

  答:有String(字符串),Hash(哈希表,一个key 对应一对 (field,value)),List(链表),set(无序集合),zset(有序集合)

2、Redis 持久化

答:Redis提供了两种持久化的机制,一种是RDB,一种是AOF。对于RDB,主要原理是使用快照文件,对Redis内存中的数据进行拷贝存到磁盘中,当Redis宕机后,可以读取磁盘中的快照文件来恢复数据。 对于AOF,主要原理是一个日志追加文件,把redis的写命令都写进日志文件中,当宕机后需要恢复数据,可以执行一遍上述日志文件的redis命令来恢复数据。

3、Redis的淘汰策略机制

答:淘汰策略主要有八种:不做处理,淘汰有TTL中最小TTL的那个,随机淘汰(两种,所有和只有TTL的),LRU(两种),LFU(两种)

4. Redis为什么快?

答:因为Redis的数据是存放在内存的,访问内存 会比访问外存更快。并且Redis是单线程的,避免了上下文的切换操作。

MySQL:

1.事务的特性?

答:事务的特性有四个,原子性、一致性、隔离性、持久性。

2.undo log 和 redo log的区别?

答: undo log 主要是记录一些逆操作,用来恢复数据,保证数据的原子性和一致性,比如当数据库执行了一条insert命令,undo log 就会记录一条delete命令。

   redo log 主要是记录数据的物理变化,服务宕机重启后可以用来同步数据

3.两种存储引擎?

4.索引?

5.锁机制

6.MVCC的原理

SSM + Springboot + SpringCloud

1.什么是IOC?

2.什么是AOP?

3.Bean的生命周期

4.循环依赖?

5.自动配置原理?

RabbitMQ

1.如何解决消息丢失问题?

答:要看是哪种消息丢失问题,因为消息是由生产者发送到交换机上,然后交换机发送到指定的消息队列上,消费者再从消息队列中拿出消息进行消费。这里统一做法是加ACK确认,每一个环节,当发送成功后,都要发送一个确认收到的ACK。

2.如何解决重复消费问题?

答:对每个业务消息绑定一个id标识,当消费后,把记录写进数据库,下次再对其进行消费时,查询一下数据库,判断这个消息是否消费过即可。

多线程

1.线程和进程的区别?

  进程就是内存中运行的应用程序,每个进程都有自己独立的内存空间,一个进程有多个线程      
  线程就是进程中的一个控制单元,多个线程共享一个内存空间,一个进程可以运行多个线程

2.并行和并发的区别?

并行是同一个时间点做多件事,并发是同一个时间段做多件事。

3.线程创建的方式有哪些?

 共有四种方式,1.继承Thread类,重写run方法。

                           2.实现Runnable接口,重写Runable的run方法,再使用Thread的构造函数把Runable实现类作为参数传入创建一个线程。

                            3.实现Callable接口,通过futureTask包装 Callable对象,再将futureTask作为对象传入Thread的构造函数,创建线程

                                4.通过线程池获取。

4.线程的start和run的区别是什么?
        start用于启动线程,run用于执行线程,
        start只能调用一次,run可以调用多次
        
        start是用来使线程进入就绪状态,当分配到时间片时便会执行,如果直接运行
        run方法,则相当于只是执行了Thread中的一个普通方法并不会启动线程。
        简单来说,Start方法会执行线程前相对应的准备工作。

5.sleep和wait的区别
          两者都可以使线程进入等待状态、但是sleep是属于Thread类、wait是属于object类
          sleep不释放锁、wait释放锁
          wait()用完后,线程不会自动执行,必须调用notify()或notifyAll()方法才能执行,
          sleep()方法调用后,线程经过过一定时间会自动苏醒,wait(参数)也可以传参数使
          其苏醒

6. notify 和notifyAll的区别   
      notify: 唤醒一个处于等待状态的进程,如果多线程在等待则需要看看优先级
      notifyAll:唤醒所有处于等待状态的线程,让他们去竞争一个锁,谁竞争到
                          就先进入就绪状态

7.  什么是线程死锁:
         死锁就是不同的线程在执行过程中都不放弃自己的资源,都在等着对方先释放资源,
         这样便形成了死锁

8.如何停止一个正在运行的线程
        1.stop方法
        2.interrupt中断线程
        3.run方法执行结束则会自动退出

        4.变量标记法

9.yield:
  可以让出cpu的使用权,是当前线程从运行状态转为就绪状态,等待cpu的下次调度,注意,yield是让出CPU使用权,但是不会释放锁等资源。

10.yield和 sleep的区别

   yield是让线程从运行状态转为就绪状态,而sleep是从运行状态变为等待状态,即被阻塞了,两者的共同点是:都不会释放锁,不同点是:除了状态转换不同,还有sleep需要处理中断异常,而yield不需要。

11.JMM (Java内存模型)

JMM (Java内存模型) 定义了共享内存中多线程程序读写操作的行为规范,JMM把内存分为两块,一块是私有线程的工作内存(每个线程的工作内存是相互隔离独立的),一块是所有线程的共享区域(主内存)。

线程和线程之间是相互隔离的,线程和线程交互需要通过主内存。

12.你谈谈对CAS的理解。

CAS(比较再交换)体现是一种乐观锁的思想,在无锁状态下保证线程操作数据的原子性(自旋锁)。

13. 谈谈对volatile的理解。

        1.实现多线程情况,线程修改共享变量后对其他线程的可见性。

                用volatile 修饰共享变量,能够防止编译器等优化发生,让一个线程对共享变量的修改对另一个线程可见。

         2.禁止对共享变量的指令重排序。

                用volatile修饰共享变量会在读、写共享变量时加入不同的屏障,阻止其他读写操作越过屏障,从而达到阻止重排序的效果。

                写操作加入屏障,可以防止其他写操作往下走

                读操作加入屏幕,可以防止其他读操作往上走

                如果是写操作的变量,尽量放到最后

                如果是读操作的变量,尽量放到最前

14.什么是AQS?

        是多线程中的队列同步器,是一种锁机制,它是作为一个基础框架使用的,像ReentrantLock都是基于AQS实现的。

        AQS内部维护了一个先进先出的双向队列,队列中存储的排队的线程

        在AQS内部有一个state属性,相当于一个锁资源,默认是0(无锁),如果队列中有一个线程修改成功了state为1,则当前线程就相当于获得了资源。

        在对state的修改,为保证原子性采用的CAS机制。

15.synchronized 和 Lock 的区别

        1.synchronized 是 关键字,源码在JVM中,用C ++ 语言实现,Lock是个接口,用Java实现

        2.两者都属于悲观锁,synchronized 在退出同步代码块后自动释放,而Lock需要手动调用 unlock方法释放。

        3.Lock的功能更全面,提供了公平锁、可打断、可超时、多条件变量,在没有竞争时,synchronized性能不赖,在竞争激烈时,Lock的实现通常有更好的性能。

16.如何进行死锁诊断?

        在命令行使用jps可以查看 死锁的进程id,然后通过 jstack  -L 进程id 即可查看死锁的日志

17.聊一下ConcurrentHashMap

        底层数据结构 跟 HashMap一致,jdk1.7之前是 数组 + 链表, jdk8 之后是数组 + 链表 + 红黑树

        加锁的方式:

        jdk1.7之前,是基于Segment进行分段加锁的,一个Segment对应多个HashEntry节点,当需要修改时,会在Segment 采用加锁的方式,锁住多个节点,只允许一个线程访问修改。

        jdk8 之后,是基于HashEntry 的首节点进行加锁,加锁粗粒度更细,比起jdk7,能更好的提高并发效率。

18.线程池中有哪些常见的阻塞队列?

        最常见的是LinkBlockingQueue和ArrayBlockingQueue,

        两者有一定区别,LinkBlocking 底层是基于链表,而ArrayBlockingQueue底层是基于数组

                                     LinkBlocking 的长度可有界也可无界,而ArrayBlockingQueue是强制有界,在创建的时候必须指定。

                                      LinkBlocking 只有在添加数据的时候才会创建节点,而ArrayBlockingQueue是提前初始化好了的

                                        LinkBlocking 底层是基于两把锁(头和尾),而ArrayBlockingQueue是一把

                                所以相对来说,LinkBlocking性能更高一点。

19.如何确定核心线程数

        对于高并发、执行时间短的,一般设置为CPU的核数 +1,减少线程上下文的切换

        并发不高,但执行时间长的,分为两类,一类是IO密集型的任务,一般设置为CPU核数 * 2 + 1 ,因为占用CPU时间短,一类是计算型任务,一般设置为CPU核数 + 1 ,因为经常占用CPU。     

20.说一下线程池的核心参数和线程池的执行原理

      线程池有七个核心参数,分别是:

                               线程池核心线程数量

                               线程池最大线程数量 (核心线程数量 + 临时线程数量)

                               临时线程存活时间

                               临时线程存活时间单位 

                                阻塞队列

                                线程工厂

                                线程拒绝策略

  线程池的执行原理:

当提交一个任务到线程池中,若有空闲的核心线程,则执行任务,如果没有空闲的核心线程,则加入到阻塞队列中,若阻塞队列满了,则会创建临时线程去执行刚提交的任务,若核心线程和临时线程均在忙碌且阻塞队列满了,则会触发拒绝策略,拒绝策略有四种:1.直接抛出异常。2.让主线程去执行。3.丢弃阻塞队列中等待最久的任务,把新提交的任务加入到队列中。4.直接丢弃新提交的任务。

21.线程池的种类有哪些?

        1.固定核心线程数的线程池 (newFixedThreadPool)(不含临时线程,阻塞队列无界 为 LinkedBlockingQueue)

               即核心线程数 和最大线程数一样,阻塞队列为LinkedBlockingQueue,最大容量为Integer的最大值

                适用于任务量已知,相对耗时的任务

        2.  单线程化的线程池 (newSingleThreadExecutor),它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO 先进先出)执行

        核心线程数和最大线程数都是1,阻塞队列为LinkedBlockingQueue,最大容量无界

        适用于需要按照顺序执行的任务   

        3.可缓存线程池  (newCachedThreadPool)

        核心线程数是0

        最大线程数是 Integer的最大值

        阻塞队列为 SynchronousQueue,即不存储元素的阻塞队列

        适合任务数比较密集,但每个任务执行时间短的情况   

        4. 可以执行延迟任务的线程池,支持定时以及周期性执行(newScheduledThreadPool)

   22. 为什么不建议使用Executors创建线程池?

        Executors创建的线程池,大多会出现OOM问题,即内存溢出,因为创建的一些线程池中的阻塞队列是无界的,会造成资源的浪费。

        而使用 new ThreadPoolExecutors创建的线程池,是自定义线程池参数的,所以可以根据自己的业务需求去制定规则,更加灵活。      

集合

JVM

计算机网络

操作系统

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值