初级JAVA开发面试题分享(二)

96 阅读7分钟

面试题由23年8月开始记录,主要参考B站黑马程序员的视频(新版Java面试专题视频教程,java八股文面试全套真题+深度详解(含大厂高频面试真题)_哔哩哔哩_bilibili)和JavaGuide(项目介绍 | JavaGuide),并在多次面试中二次改进并增加题目。内容仅供参考,建议理解使用。

多线程(基础频率高,问过线程池)

基础知识

线程和进程的区别?

建议自己理解并举例回答,如举例微信与公众号的关系(微信为进程,公众号为线程)

image-20230903142452969.png

image-20230903142530888.png

image-20230903142643498.png

并行和并发有什么区别?

建议自己理解并举例回答

image-20230903213516953.png image-20230903213908191.png image-20230903214534481.png

创建线程的方式有哪些?(大概率问)

  • 继承Thread类
  • 实现runable接口
  • 实现Callable接口
  • 线程池创建
  • 使用匿名内部类(本质上也是上面四种)
  1. 继承Thread类: 创建一个类继承自Thread类,并重写其run()方法。然后创建这个类的实例,并调用其start()方法来启动线程。

    public class MyThread extends Thread {
        @Override
        public void run() {
            // 线程要执行的代码
        }
    }
    
    // 在其他类中使用
    MyThread myThread = new MyThread();
    myThread.start();
    
  2. 实现Runnable接口: 创建一个类实现Runnable接口,并实现其run()方法。然后将Runnable实例传递给Thread对象,最后调用Thread对象的start()方法。

    public class MyRunnable implements Runnable {
        @Override
        public void run() {
            // 线程要执行的代码
        }
    }
    
    // 在其他类中使用
    Thread thread = new Thread(new MyRunnable());
    thread.start();
    
  3. 实现Callable接口: 与Runnable类似,但Callable允许任务返回值,并且可以抛出异常。Callable任务需要借助FutureTask包装器来创建Thread。

    import java.util.concurrent.Callable;
    import java.util.concurrent.FutureTask;
    
    public class MyCallable implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            // 线程要执行的代码,并返回结果
            return 123;
        }
    }
    
    // 在其他类中使用
    FutureTask<Integer> futureTask = new FutureTask<>(new MyCallable());
    Thread thread = new Thread(futureTask);
    thread.start();
    
    // 获取任务结果
    Integer result = futureTask.get();
    
  4. 使用Executor框架: Java 5引入了基于固定池大小的线程池的Executors类,可以创建不同类型的线程池来管理线程。使用Executors可以简化线程的创建和管理。

    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    // 创建一个固定大小的线程池
    ExecutorService executor = Executors.newFixedThreadPool(10);
    
    // 提交任务
    executor.execute(new MyRunnable());
    
    // 关闭线程池
    executor.shutdown();
    
  5. 使用匿名内部类: 在某些情况下,可以使用匿名内部类来快速创建线程,特别是当线程只需要执行一次任务时。

    // 使用Thread的匿名内部类
    new Thread(new Runnable() {
        @Override
        public void run() {
            // 线程要执行的代码
        }
    }).start();
    
    // 或者使用Callable的匿名内部类
    FutureTask<Integer> futureTask = new FutureTask<>(new Callable<Integer>() {
        @Override
        public Integer call() throws Exception {
            // 线程要执行的代码,并返回结果
            return 123;
        }
    });
    
    Thread thread = new Thread(futureTask);
    thread.start();
    

Runable和Callable的区别(常见面试题,可能会问)

image.png

run()和start()的区别(常见面试题,可能会问)

image.png

线程包括哪些状态,状态之间是如何变化的?

image.png

image.png

image.png

新建T1、T2、T3三个线程,如何保证它们按顺序执行?

image.png

Java中wait和sleep方法的不同?(常见面试题,可能会问)

image.png

如何停止一个正在运行的线程?

image.png

并发安全(基本没被问过)

synchronized关键字的底层原理

image.png

image.png

image.png

image.png

Monitor实现的锁属于重量级锁,你了解过锁升级吗?

这里只给出结论,详细的可以去B站看视频

image.png

谈一谈JMM(Java内存模型)

image.png

image.png

知道CAS吗?

image.png

image.png

image.png

谈谈对volatile的理解

image.png

什么是AQS?

image.png

image.png

image.png

ReentrantLock的实现原理

image.png

image.png

image.png

image.png

synchronized和Lock有什么区别?(问过)

image.png

死锁产生的条件是什么?

image.png

image.png

聊一下ConcurrentHashMap?(问过)

image.png

image.png

image.png

导致并发程序出现问题的根本原因是什么(Java程序中怎么保证多线程的执行安全)

Java并发编程的三大特性

  • 原子性

    • 一个线程在CPU中操作不可暂停,也不可中断,要么执行完成,要么不执行
  • 可见性

    • 让一个线程对共享变量的修改对另一个线程可见
  • 有序性

    • 程序在执行的时候,程序的代码执行顺序和语句的顺序是一致的

image.png

线程池(基本都被问过)

说一下线程池的核心参数,线程池的执行原理知道吗

image.png

image.png

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

image.png

image.png

如何确定核心线程数

image.png

image.png

线程池的种类有哪些

image.png

image.png

image.png

image.png

image.png

线程池的拒绝策略

  • AbortPolicy

    • 第一种拒绝策略是 AbortPolicy,这种拒绝策略在拒绝任务时,会直接抛出一个类型为 RejectedExecutionException的RuntimeException,让你感知到任务被拒绝了,于是你便可以根据业务逻辑选择重试或者放弃提交等策略。
  • DiscardPolicy

    • 第2种拒绝策略是 DiscardPolicy,这种拒绝策略正如它的名字所描述的一样,当新任务被提交后直接被丢弃掉,也不会给你任何的通知,相对而言存在一定的风险,因为我们提交的时候根本不知道这个任务会被丢弃,可能造成数据丢失。
  • DiscardOldestPolicy

    • 第3种拒绝策略是 DiscardOldestPolicy,如果线程池没被关闭且没有能力执行,则会丢弃任务队列中的头结点,通常是存活时间最长的任务,这种策略与第二种不同之处在于它丢弃的不是最新提交的,而是队列中存活时间最长的,这样就可以腾出空间给新提交的任务,但同理它也存在一定的数据丢失风险。
  • CallerRunsPolicy

    • 第4种拒绝策略是 CallerRunsPolicy,相对而言它就比较完善了,当有新任务提交后,如果线程池没被关闭且没有能力执行,则把这个任务交于提交任务的线程执行,也就是谁提交任务,谁就负责执行任务。这样做主要有两点好处。
    • 第一点新提交的任务不会被丢弃,这样也就不会造成业务损失。
    • 第二点好处是,由于谁提交任务谁就要负责执行任务,这样提交任务的线程就得负责执行任务,而执行任务又是比较耗时的,在这段期间,提交任务的线程被占用,也就不会再提交新的任务,减缓了任务提交的速度,相当于是一个负反馈。在此期间,线程池中的线程也可以充分利用这段时间来执行掉一部分任务,腾出一定的空间,相当于是给了线程池一定的缓冲期。

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

image.png

使用场景(没被问过,此处仅给出例子,具体可看B站)

项目中哪里使用了多线程

ES数据批量导入
数据汇总
异步调用

如何控制某个方法允许并发访问线程的数量

其他

谈谈对ThreadLocal的理解

image.png

image.png

image.png

image.png

ThreadLocal--内存泄露问题

image.png

image.png

image.png

JVM(没被问过,但建议掌握并在面试中找机会提及)

image.png

image.png

JVM组成

什么是程序计数器

image.png

image.png

image.png

能详细介绍Java堆吗?

image.png

image.png

image.png

什么是虚拟机栈

image.png

能不能解释下方法区?

image.png image.png image.png image.png

听过直接内存吗?

image.png

类加载器

什么是类加载器,类加载器有哪些

image.png

image.png

image.png

什么是双亲委派模型?

image.png

说一下类装载的执行过程?

image.png

image.png

垃圾回收

对象什么时候可以被垃圾回收器回收?

image.png

JVM垃圾回收算法有哪些?

image.png

说一下JVM中的分代回收

image.png

说一下JVM有哪些垃圾回收器?

image.png

强引用、软引用、弱引用、虚引用的区别?

image.png

JVM实践

JVM调优的参数在哪里设置参数值

image.png

image.png

image.png

JVM调优参数有哪些?

image.png

说一下JVM调优的工具?

image.png

Java内存泄露的排查思路?

image.png

CPU飚高排查方案与思路?

image.png

未完待续,有空继续