Java高频面试之并发编程-07

hello啊,各位观众姥爷们!!!本baby今天来报道了!哈哈哈哈哈嗝🐶

面试官:线程之间有哪些通信方式?

在 Java 多线程编程中,线程间通信(Inter-Thread Communication)的核心目的是协调不同线程的执行顺序或共享数据。以下是线程间通信的常见方式及其实现原理和应用场景:


1. 共享内存 + 同步机制

原理 :线程通过共享变量(如对象、集合)交换数据,通过锁(synchronizedLock)或原子类(AtomicInteger 等)保证线程安全。
示例

java 复制代码
// 共享变量
private int sharedValue = 0;
private final Object lock = new Object();

// 线程 A 写入
synchronized (lock) {
    sharedValue = 42;
    lock.notifyAll(); // 通知等待的线程
}

// 线程 B 读取
synchronized (lock) {
    while (sharedValue == 0) {
        lock.wait(); // 等待通知
    }
    System.out.println(sharedValue);
}

适用场景:简单的数据共享,需手动处理同步和竞态条件。


2. 阻塞队列(BlockingQueue)

原理 :线程通过线程安全的队列传递数据,生产者写入队列,消费者从队列读取。队列满或空时自动阻塞。
示例

java 复制代码
BlockingQueue<String> queue = new LinkedBlockingQueue<>(10);

// 生产者线程
queue.put("data"); // 队列满时阻塞

// 消费者线程
String data = queue.take(); // 队列空时阻塞

适用场景:生产者-消费者模型,解耦生产与消费逻辑。


3. wait() / notify() / notifyAll()

原理 :基于对象监视器(Monitor)的等待-通知机制,需在 synchronized 块中使用。
示例

java 复制代码
public class TaskCoordinator {
    private boolean isReady = false;

    public void waitForReady() throws InterruptedException {
        synchronized (this) {
            while (!isReady) {
                this.wait(); // 释放锁并等待
            }
        }
    }

    public void setReady() {
        synchronized (this) {
            isReady = true;
            this.notifyAll(); // 唤醒所有等待线程
        }
    }
}

适用场景:线程间的条件协作(如任务启动前的等待)。


4. 同步工具类(Semaphore、CountDownLatch 等)

原理 :通过计数器或状态控制线程的执行流程。
常用类

  • CountDownLatch :等待多个线程完成初始化。

    java 复制代码
    CountDownLatch latch = new CountDownLatch(3);
    
    // 工作线程
    latch.countDown(); // 计数器减 1
    
    // 主线程
    latch.await(); // 等待计数器归零
  • CyclicBarrier :多线程相互等待至屏障点。

    java 复制代码
    CyclicBarrier barrier = new CyclicBarrier(3);
    
    // 每个线程执行到屏障点后等待
    barrier.await();
  • Semaphore :控制并发线程数量。

    java 复制代码
    Semaphore semaphore = new Semaphore(5);
    
    semaphore.acquire(); // 获取许可(无可用许可时阻塞)
    semaphore.release(); // 释放许可

适用场景:复杂线程协作(如分批任务、资源池管理)。


5. 管道(PipedInputStream / PipedOutputStream)

原理 :通过管道流直接传递字节数据,需成对使用。
示例

java 复制代码
PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream();
pis.connect(pos); // 连接输入输出流

// 生产者线程写入数据
pos.write("data".getBytes());

// 消费者线程读取数据
int data = pis.read();

适用场景:线程间直接传输字节数据(较少使用,性能较低)。


6. Future 和 Callable

原理 :通过 Future 获取另一个线程的异步执行结果。
示例

java 复制代码
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Integer> future = executor.submit(() -> {
    Thread.sleep(1000);
    return 42;
});

// 阻塞等待结果
int result = future.get();

适用场景:异步任务执行与结果获取。


7. 事件驱动(如 EventBus)

原理 :基于发布-订阅模式,线程通过事件总线传递消息。
示例(使用 Guava EventBus)

java 复制代码
EventBus eventBus = new EventBus();

// 订阅者
class Subscriber {
    @Subscribe
    public void handleEvent(String event) {
        System.out.println("Received: " + event);
    }
}

eventBus.register(new Subscriber());

// 发布者线程
eventBus.post("Hello");

适用场景:松耦合的事件通知(如 GUI 事件处理)。


8. 回调(Callback)

原理 :线程 A 调用线程 B 的方法时传入回调函数,线程 B 完成任务后调用回调函数通知线程 A。
示例

java 复制代码
interface Callback {
    void onComplete(String result);
}

class Worker {
    void doWork(Callback callback) {
        new Thread(() -> {
            String result = "Done";
            callback.onComplete(result);
        }).start();
    }
}

// 调用
new Worker().doWork(result -> System.out.println(result));

适用场景:异步任务完成后的通知。


对比与选型建议

通信方式 优点 缺点 适用场景
共享内存 + 同步 简单直接 需手动处理同步,易出错 简单数据共享
阻塞队列 线程安全,解耦生产消费 队列容量需合理设置 生产者-消费者模型
wait/notify 灵活的条件控制 需搭配 synchronized 使用 线程条件协作
同步工具类 简化复杂协作逻辑 需理解不同工具的特性 多线程分阶段协作
Future/Callable 支持异步结果获取 仅适用于单次任务 异步任务执行
事件驱动 松耦合,易扩展 依赖第三方库(如 EventBus) 事件通知场景
回调 灵活定制逻辑 回调嵌套可能导致"回调地狱" 异步任务完成通知

注意事项

  1. 线程安全:共享变量必须通过锁或原子类确保可见性和原子性。
  2. 死锁预防:避免嵌套锁和循环等待资源。
  3. 性能权衡 :高并发场景优先选择无锁或细粒度锁(如 ConcurrentHashMap)。
  4. 资源释放 :确保 wait() 后能正常唤醒,避免线程永久阻塞。
相关推荐
Baihai_IDP2 小时前
为什么 AI 巨头们放弃私有壁垒,争相拥抱 Agent Skills
人工智能·面试·llm
Moment2 小时前
Agent 开发本质上就是高级点的 CRUD
前端·后端·面试
Seven972 小时前
NIO的零拷贝如何实现高效数据传输?
java
哈里谢顿13 小时前
0305乒乓xx agent运维开发岗面试记录
面试
哈里谢顿13 小时前
0309面试二总结
面试
哈里谢顿13 小时前
0309面试一记录
面试
哈里谢顿13 小时前
0310面试二记录
面试
哈里谢顿14 小时前
0310面试记录一
面试
boooooooom16 小时前
讲清 Proxy + effect + track/trigger 流程
javascript·vue.js·面试
架构师沉默16 小时前
别又牛逼了!AI 写 Java 代码真的行吗?
java·后端·架构