Java 常见的多线程面试题

在Java开发中,多线程编程是一个非常重要的技能,也是面试中的常见考点。本文将围绕一些经典的多线程面试题展开,从基础概念到高级应用,帮助你深入理解Java多线程的核心原理与实践。


1. 多线程的基本概念

什么是线程?线程与进程有什么区别?

线程是CPU调度的最小单位,而进程是操作系统资源分配的最小单位。一个进程可以包含多个线程,这些线程共享进程的内存空间和资源。

线程的生命周期包括哪些状态?

线程生命周期包括以下状态:

  • 新建(New):线程对象被创建,但尚未启动。
  • 可运行(Runnable):线程被启动,等待CPU调度。
  • 运行(Running):线程正在执行。
  • 阻塞(Blocked):线程因等待资源而暂停。
  • 终止(Terminated):线程执行结束。

2. 线程创建与启动

Java中创建线程的方式有哪些?

  1. 继承Thread

    class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("Thread is running");
        }
    }
    new MyThread().start();
    
  2. 实现Runnable接口

    class MyRunnable implements Runnable {
        @Override
        public void run() {
            System.out.println("Thread is running");
        }
    }
    new Thread(new MyRunnable()).start();
    
  3. 使用CallableFuture

    import java.util.concurrent.Callable;
    import java.util.concurrent.FutureTask;
    
    class MyCallable implements Callable<String> {
        @Override
        public String call() {
            return "Thread is running";
        }
    }
    
    FutureTask<String> task = new FutureTask<>(new MyCallable());
    new Thread(task).start();
    System.out.println(task.get());
    

3. 线程安全与同步

如何保证线程安全?

线程安全是指多线程环境下,代码的执行结果与单线程环境下结果一致。常见的解决方案包括:

  1. 使用synchronized关键字

    • 修饰方法:
      public synchronized void method() {
          // Critical section
      }
      
    • 修饰代码块:
      public void method() {
          synchronized (this) {
              // Critical section
          }
      }
      
  2. 使用Lock接口

    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    Lock lock = new ReentrantLock();
    lock.lock();
    try {
        // Critical section
    } finally {
        lock.unlock();
    }
    
  3. 使用线程安全的集合类
    Java提供了如ConcurrentHashMapCopyOnWriteArrayList等线程安全集合类。

死锁是什么?如何避免?

死锁是指两个或多个线程相互等待对方释放资源,导致所有线程都无法继续执行。避免死锁的方法:

  • 避免嵌套锁。
  • 按统一顺序获取锁。
  • 使用尝试锁(如tryLock方法)。

4. 线程间通信

线程间如何通信?

  1. 使用waitnotifynotifyAll

    class SharedResource {
        private boolean flag = false;
    
        public synchronized void produce() throws InterruptedException {
            while (flag) {
                wait();
            }
            System.out.println("Producing...");
            flag = true;
            notify();
        }
    
        public synchronized void consume() throws InterruptedException {
            while (!flag) {
                wait();
            }
            System.out.println("Consuming...");
            flag = false;
            notify();
        }
    }
    
  2. 使用BlockingQueue

    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.ArrayBlockingQueue;
    
    BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
    
    // Producer
    new Thread(() -> {
        try {
            queue.put(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }).start();
    
    // Consumer
    new Thread(() -> {
        try {
            System.out.println(queue.take());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }).start();
    

5. 高级多线程知识

什么是线程池?如何使用线程池?

线程池通过复用线程来减少频繁创建和销毁线程的开销。Java通过ExecutorService接口提供线程池支持。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

ExecutorService executor = Executors.newFixedThreadPool(5);

for (int i = 0; i < 10; i++) {
    executor.execute(() -> {
        System.out.println("Thread is running");
    });
}

executor.shutdown();

volatile关键字的作用是什么?

  • 保证变量的可见性:一个线程修改了变量,其他线程可以立即看到。
  • 禁止指令重排序。

什么是乐观锁与悲观锁?

  • 悲观锁:认为并发操作会发生冲突,通过加锁避免冲突。
  • 乐观锁:认为并发操作通常不会冲突,通过版本号或CAS机制检测冲突。

6. 经典面试题

  1. 写一个线程安全的单例模式

    class Singleton {
        private static volatile Singleton instance;
    
        private Singleton() {}
    
        public static Singleton getInstance() {
            if (instance == null) {
                synchronized (Singleton.class) {
                    if (instance == null) {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    
  2. 用Java实现生产者-消费者模型
    详见BlockingQueue的实现部分。

  3. 解释线程的上下文切换
    线程上下文切换是指CPU从一个线程切换到另一个线程时保存和恢复线程状态的过程,可能引起性能开销。


7. 总结

Java多线程是一个宽泛而深入的领域,面试时需要既掌握基础概念又能够处理实际问题。通过以上的经典问题和代码示例,相信你能更好地准备多线程相关的面试。

希望这篇博客对你有所帮助!如果你有其他Java多线程问题,欢迎留言交流。

posted @   hyzz123  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤
点击右上角即可分享
微信分享提示