HDFS await()和interrupt()引起的死循环问题分析

本文深入解析HDFS 2.7版本中短路读功能存在的DomainSocketWatcher类Bug,涉及线程通信代码中await与interrupt处理不当导致的死循环问题,并通过实测对比await与awaitUninterruptibly方法的区别。

1.背景

hdfs短路读利用UNIX域套接字,可以让客户端和DataNode通信(客户端与dn是同一台机器)。需要在datanode和客户端的配置中都配置一个套接字路径,并且开启短路读特性。官方链接

hdfs在短路读时, 2.7版本的代码中DomainSocketWatcher(linux机器进程的socket通信的监听)类中有个bug需要修复。分析如下:

//DomainSocketWatcher#add相关代码
public void add(DomainSocket sock, Handler handler) {
   
   
  lock.lock();
  try {
   
   
    Entry entry = new Entry(sock, handler);
    toAdd.add(entry);
    while (true) {
   
   
      try {
   
   
        processedCond.await();
      } catch (InterruptedException e) {
   
   
        Thread.currentThread().interrupt();
      }
      if (!toAdd.contains(entry)) {
   
   
        break;
      }
    }
  } finally {
   
   
    lock.unlock();
  }
}
//DomainSocketWatcher#remove相关代码
public void remove(DomainSocket sock) {
   
   
  lock.lock();
  try {
   
   
    toRemove.put(sock.fd, sock);
    while (true) {
   
   
      try {
   
   
        processedCond.await();
      } catch (InterruptedException e) {
   
   
        Thread.currentThread().interrupt();
      }
      if (!toRemove.containsKey(sock.fd)) {
   
   
        break;
      }
    }
  } finally {
   
   
    lock.unlock();
  }
}
final Thread watcherThread = new Thread(new Runnable() {
   
   
  @Override
  public void run() {
   
     
    final TreeMap<Integer, Entry> entries = new TreeMap<Integer, Entry>();
    try {
   
   
      while (true) {
   
   
        lock.lock();
        try {
   
   
            // Handle pending removals
            while (true) {
   
   
   
<think> 我们注意到用户的问题是关于Java中InterruptedException的导入使用。根据引用内容,InterruptedException是Java中的一个异常类,它在多线程编程中用于表示线程被中断。用户询问的是“导入”InterruptedException,实际上在Java中,异常类不需要像某些语言那样显式导入(import),因为它们在java.lang包中,而java.lang包是自动导入的。但是,如果用户指的是在代码中如何处理这个异常,那么我们可以详细解释。 引用[1]提到:当不能抛出InterruptedException时,必须捕获它并恢复中断状态(通过调用Thread.currentThread().interrupt())。引用[2]展示了一个方法声明抛出了InterruptedException。引用[3]展示了在CountDownLatch的await()方法中捕获InterruptedException,并将其包装成RuntimeException抛出。引用[4]则是一个报错信息,显示了InterruptedException的发生。 因此,我们将重点放在InterruptedException的使用场景处理方法上。 回答结构: 1. InterruptedException的概述:介绍这个异常的含义发生场景。 2. 如何处理InterruptedException:分为两种情况:可以抛出不能抛出。 3. 代码示例:展示如何正确捕获处理InterruptedException。 4. 注意事项:强调恢复中断状态的重要性。 5. 相关问题。 注意:在代码示例中,我们将使用Java代码,并确保正确捕获处理InterruptedException。 </think> ### Java中`InterruptedException`的原理与处理方法 `InterruptedException`是Java多线程编程中的核心异常类,用于表示线程被中断。以下是其关键特性处理方法: #### 1. 异常来源与触发场景 - **中断机制**:Java通过`thread.interrupt()`发送中断请求,目标线程在阻塞状态(如`sleep()/wait()/join()`)会立即抛出`InterruptedException`[^1] - **典型触发点**: ```java Thread.sleep(1000); // 睡眠时被中断 object.wait(); // 等待条件队列 latch.await(); // CountDownLatch等待[^3] BlockingQueue.take(); // 阻塞队列操作 ``` #### 2. 异常处理规范 - **原则**:必须合理响应中断请求,禁止忽略异常 - **两种标准处理方式**: **① 传递中断**(优先选择): ```java void task() throws InterruptedException { Thread.sleep(1000); // 直接抛出给调用者 } ``` **② 恢复中断状态**(无法抛出时): ```java try { Thread.sleep(1000); } catch (InterruptedException e) { // 1. 执行必要的清理操作 cleanResources(); // 2. 恢复中断状态(关键步骤) Thread.currentThread().interrupt(); // [^1] // 3. 可选:包装为运行时异常 throw new RuntimeException("Task interrupted", e); // [^3] } ``` #### 3. 中断处理误区 - **错误做法1(静默吞没异常)**: ```java catch (InterruptedException e) {} // 导致中断信号丢失 ``` - **错误做法2(仅打印日志)**: ```java catch (InterruptedException e) { logger.error("Interrupted", e); // 未恢复中断状态 } ``` - **后果**:上层代码无法感知中断,可能导致线程池无法关闭或资源泄漏[^4] #### 4. 实际应用场景 - **批量任务中断**(如引用[3]案例): ```java public void importData(List<Dto> list) { CountDownLatch latch = new CountDownLatch(N); // ...启动多线程任务... try { latch.await(5, TimeUnit.MINUTES); // 超时等待 } catch (InterruptedException e) { Thread.currentThread().interrupt(); // 恢复状态 throw new ImportException("导入被取消"); } } ``` - **框架级中断处理**(如Sqoop/HDFS): ```java void writeData() { try { hdfsOutputStream.write(...); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // 恢复标记 throw new HdfsIOException(e); // 转换异常类型[^4] } } ``` #### 5. 设计原则 1. **快速响应**:捕获后立即执行清理操作 2. **状态保留**:必须调用`interrupt()`维持中断标记 3. **资源释放**:确保打开的文件/网络连接被关闭 4. **异常转换**:根据场景转换为业务合适的异常类型
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值