Java多线程面试通关秘籍:从入门到实战的5大核心考点(附高频真题解析)

引言:为什么面试官总爱问多线程?(建议全文背诵!)

老铁们有没有发现,Java面试中多线程问题就像打不死的BOSS,每次必出!根据某大厂内部数据,初级开发岗的多线程考察率高达87%!但别慌,今天咱们用最接地气的方式,把多线程考点掰开揉碎了讲明白!

📚 高频考点速览

  1. 线程与进程的相爱相杀(必考题!)
  2. 创建线程的3种祖传秘方(最后一个90%人不知道!)
  3. 线程生命周期的6种状态转换(画图记忆法)
  4. synchronized与Lock的世纪对决(附性能对比表)
  5. 线程池的7大核心参数(工作五年都可能踩坑)

一、线程 vs 进程:别再说分不清了!

1.1 本质区别(面试官最爱问!)

  • 进程:操作系统分配资源的单位(内存、CPU等),相当于独立运行的APP
  • 线程:CPU调度的基本单位,一个进程至少1个线程(主线程)

举个栗子🌰:Chrome浏览器是多进程架构,每个标签页是独立进程;而每个网页里的JS动画、网络请求都是线程在工作

1.2 通信方式对比

进程间通信线程间通信
实现方式管道、消息队列、共享内存共享变量、wait/notify
开销大(需要内核介入)小(直接内存访问)

二、创建线程的3种姿势(最后一个超实用!)

2.1 继承Thread类(新手村装备)

// 注意:实际开发慎用!会导致无法继承其他类
class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("线程启动!");
    }
}
// 使用方式
new MyThread().start();

2.2 实现Runnable接口(推荐!)

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("实现Runnable更灵活!");
    }
}
// 通过Thread启动
new Thread(new MyRunnable()).start();

2.3 使用Callable+Future(带返回值的黑科技!)

Callable<String> task = () -> {
    Thread.sleep(1000);
    return "异步结果";
};

FutureTask<String> future = new FutureTask<>(task);
new Thread(future).start();

// 获取结果(会阻塞!)
String result = future.get(); 

三、线程生命周期6种状态(附状态转换图)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(注:此处应有图,但遵守规则不放图)

状态迁移口诀(背熟保命!)

  1. 新建(New)就绪(Runnable):调用start()
  2. 运行(Running)阻塞(Blocked):遇到synchronized锁
  3. 运行等待(Waiting):调用wait()
  4. 运行超时等待(Timed_Waiting):调用sleep(1000)
  5. 运行终止(Terminated):run()执行完毕

四、线程安全三大杀器(高并发必备!)

4.1 synchronized锁(重要考点!!)

// 对象锁(锁住当前实例)
public synchronized void method() {}

// 类锁(锁住整个类)
public static synchronized void staticMethod() {}

// 同步代码块(更灵活)
public void safeMethod() {
    synchronized(lockObject) {
        // 临界区代码
    }
}

4.2 ReentrantLock(性能更好!)

Lock lock = new ReentrantLock();

void safeMethod() {
    lock.lock();
    try {
        // 业务代码
    } finally {
        lock.unlock(); // 必须放在finally!
    }
}

4.3 volatile关键字(最容易误解!)

  • 作用:保证可见性,禁止指令重排序
  • 不能保证原子性(比如i++操作)
  • 适用场景:状态标志位、双重检查锁

五、线程池7大参数(阿里面试题原题!)

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    corePoolSize, // 核心线程数(长期保留)
    maximumPoolSize, // 最大线程数(临时工上限)
    keepAliveTime, // 闲置线程存活时间
    TimeUnit.MILLISECONDS, // 时间单位
    new LinkedBlockingQueue<>(100), // 工作队列(缓冲用)
    Executors.defaultThreadFactory(), // 线程工厂
    new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
);

四种拒绝策略对比(选择困难症注意!)

  1. AbortPolicy:直接抛出异常(默认)
  2. CallerRunsPolicy:让主线程执行任务
  3. DiscardPolicy:默默丢弃任务
  4. DiscardOldestPolicy:丢弃队列最老的任务

🚀 实战技巧(血泪经验!)

  1. 使用ThreadLocal保存线程私有数据(但要注意内存泄漏!)
  2. 优先使用线程池而不是new Thread(资源管理很重要!)
  3. 用CompletableFuture处理复杂异步任务(Java8+)
  4. 调试多线程程序时,试试Thread.dumpStack()

高频面试题自测(答案见评论区)

  1. wait()和sleep()的根本区别是?
  2. synchronized锁升级过程是怎样的?
  3. 为什么推荐用ThreadPoolExecutor而不是Executors?
  4. volatile能替代synchronized吗?为什么?
  5. 如何实现三个线程交替打印ABC?

总结与建议

多线程就像学游泳,看一百遍教程不如自己写几个demo!建议把本文代码都手敲一遍,遇到问题欢迎在评论区讨论(24小时在线回复!)。下期预告:《Spring循环依赖的九种破解姿势》,关注不迷路~

💡 小贴士:面试被问多线程时,可以主动画状态转换图,瞬间提升面试官好感度!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值