ZetCode

Java InterruptedIOException 类

最后修改时间:2025 年 4 月 16 日

java.io.InterruptedIOException 表示 I/O 操作已被中断。 当执行 I/O 的线程被中断时,会抛出此异常。 此异常继承自 IOException 并包含 bytesTransferred 字段。

InterruptedIOException 通常发生在阻塞 I/O 操作期间。 bytesTransferred 字段指示中断前传输了多少数据。 这有助于应用程序从中断处恢复操作。

InterruptedIOException 类概述

InterruptedIOException 是 Java I/O 系统中的检查型异常。 它包含一个公共字段 bytesTransferred,用于跟踪部分传输计数。 该类被各种 I/O 类(如 Socket 和 URLConnection)使用。

public class InterruptedIOException extends IOException {
    public int bytesTransferred = 0;
    public InterruptedIOException();
    public InterruptedIOException(String s);
}

上面的代码显示了 InterruptedIOException 的结构。 bytesTransferred 字段是公共的,可以直接访问。 两个构造函数允许创建带有或不带有消息的异常。

InterruptedIOException 基础示例

此示例演示了在网络操作期间捕获 InterruptedIOException。 我们通过手动创建和中断线程来模拟中断。

Main.java
import java.io.*;
import java.net.*;

public class Main {

    public static void main(String[] args) {
        Thread ioThread = new Thread(() -> {
            try {
                URL url = new URL("http://example.com");
                URLConnection conn = url.openConnection();
                InputStream in = conn.getInputStream();
                
                byte[] buffer = new byte[1024];
                int bytesRead = in.read(buffer);
                System.out.println("Read " + bytesRead + " bytes");
                
                in.close();
            } catch (InterruptedIOException e) {
                System.out.println("I/O interrupted after " + 
                    e.bytesTransferred + " bytes");
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        
        ioThread.start();
        ioThread.interrupt(); // Simulate interruption
    }
}

此示例创建一个尝试从 URL 读取的线程。 线程立即被中断,这可能会导致 InterruptedIOException。 catch 块处理异常并报告传输的字节数。

使用 InterruptedIOException 处理 Socket 超时

Socket 操作在超时时可能会抛出 InterruptedIOException。 此示例演示了如何在客户端-服务器通信中处理此类情况。

Main.java
import java.io.*;
import java.net.*;

public class Main {

    public static void main(String[] args) {
        try {
            Socket socket = new Socket();
            socket.setSoTimeout(1000); // Set 1 second timeout
            
            // This will timeout and throw InterruptedIOException
            socket.connect(new InetSocketAddress("example.com", 80));
            
        } catch (InterruptedIOException e) {
            System.out.println("Socket operation timed out after " + 
                e.bytesTransferred + " bytes transferred");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例演示了 socket 超时处理。 setSoTimeout 方法设置 1 秒超时。 如果未及时建立连接,则会抛出 InterruptedIOException,我们捕获并处理它。

恢复中断的文件传输

此示例演示了如何使用 InterruptedIOException 的 bytesTransferred 字段在中断后恢复文件传输。

Main.java
import java.io.*;
import java.util.Random;

public class Main {

    public static void main(String[] args) {
        Random random = new Random();
        File source = new File("source.dat");
        File dest = new File("dest.dat");
        
        try (InputStream in = new FileInputStream(source);
             OutputStream out = new FileOutputStream(dest)) {
            
            byte[] buffer = new byte[1024];
            int totalRead = 0;
            
            while (true) {
                try {
                    int bytesRead = in.read(buffer);
                    if (bytesRead == -1) break;
                    
                    out.write(buffer, 0, bytesRead);
                    totalRead += bytesRead;
                    
                    // Simulate random interruption
                    if (random.nextInt(100) < 5) {
                        throw new InterruptedIOException();
                    }
                } catch (InterruptedIOException e) {
                    System.out.println("Transfer interrupted at " + 
                        totalRead + " bytes. Resuming...");
                }
            }
            
            System.out.println("Transfer completed: " + totalRead + " bytes");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例模拟可能被中断的文件传输。 发生中断时,传输从中断的地方恢复。 此处未使用 bytesTransferred 字段,因为我们手动跟踪进度。

自定义 InterruptedIOException 处理

此示例演示了如何为 InterruptedIOException 创建自定义处理程序,该处理程序实现带有退避的重试逻辑。

Main.java
import java.io.*;
import java.net.*;

public class Main {

    public static void main(String[] args) {
        int maxRetries = 3;
        int retryCount = 0;
        long backoffTime = 1000; // 1 second
        
        while (retryCount < maxRetries) {
            try {
                URL url = new URL("http://example.com/largefile");
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                
                try (InputStream in = conn.getInputStream()) {
                    byte[] buffer = new byte[8192];
                    int bytesRead;
                    
                    while ((bytesRead = in.read(buffer)) != -1) {
                        // Process data here
                    }
                    
                    System.out.println("Download completed successfully");
                    break;
                }
            } catch (InterruptedIOException e) {
                retryCount++;
                System.out.println("Attempt " + retryCount + " interrupted after " +
                    e.bytesTransferred + " bytes. Retrying in " + 
                    (backoffTime/1000) + " seconds...");
                
                try {
                    Thread.sleep(backoffTime);
                    backoffTime *= 2; // Exponential backoff
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
                break;
            }
        }
        
        if (retryCount >= maxRetries) {
            System.out.println("Max retries reached. Operation failed.");
        }
    }
}

此示例实现了一个具有重试逻辑的强大下载器。 发生 InterruptedIOException 时,它会等待并以指数退避方式重试。 bytesTransferred 字段有助于跟踪重试之间的进度。

多线程环境中的 InterruptedIOException

此示例演示了 InterruptedIOException 如何在多线程应用程序中发生以及如何正确处理它。

Main.java
import java.io.*;
import java.net.*;
import java.util.concurrent.*;

public class Main {

    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(2);
        Future future = executor.submit(() -> {
            try {
                ServerSocket server = new ServerSocket(8080);
                System.out.println("Server started");
                
                while (!Thread.currentThread().isInterrupted()) {
                    try {
                        Socket client = server.accept();
                        System.out.println("Client connected");
                        
                        InputStream in = client.getInputStream();
                        byte[] buffer = new byte[1024];
                        int bytesRead;
                        
                        while ((bytesRead = in.read(buffer)) != -1) {
                            // Process client data
                        }
                        
                        client.close();
                    } catch (InterruptedIOException e) {
                        System.out.println("Accept interrupted");
                        break;
                    }
                }
                
                server.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        
        try {
            Thread.sleep(2000);
            future.cancel(true); // Interrupt the server thread
            executor.shutdown();
            executor.awaitTermination(1, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

此示例演示了一个可以正常中断的服务器。 当线程被中断时,accept 方法可能会抛出 InterruptedIOException。 我们捕获此异常以正确清理资源。

带有 NIO 通道的 InterruptedIOException

虽然 NIO 通道通常使用不同的中断机制,但某些操作仍然可以抛出 InterruptedIOException。 此示例显示了这样一种情况。

Main.java
import java.io.*;
import java.net.*;
import java.nio.channels.*;

public class Main {

    public static void main(String[] args) {
        try {
            SocketChannel channel = SocketChannel.open();
            channel.configureBlocking(true);
            
            Thread interruptThread = new Thread(() -> {
                try {
                    Thread.sleep(1000);
                    channel.close(); // Force interruption
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
            
            interruptThread.start();
            
            try {
                channel.connect(new InetSocketAddress("example.com", 80));
            } catch (InterruptedIOException e) {
                System.out.println("Channel connection interrupted");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此示例演示了在阻塞操作期间关闭通道如何导致 InterruptedIOException。 我们启动一个单独的线程以在延迟后关闭通道,从而中断连接尝试。

来源

Java InterruptedIOException 类文档

在本文中,我们介绍了 Java InterruptedIOException 类的基本方面。 理解此异常对于构建可以优雅地处理中断的强大 I/O 操作至关重要。

作者

我的名字是 Jan Bodnar,我是一位敬业的程序员,在该领域拥有多年的经验。 我于 2007 年开始撰写编程文章,至今已撰写了 1,400 多篇文章和八本电子书。 凭借超过八年的教学经验,我致力于分享我的知识并帮助他人掌握编程概念。

列出所有Java教程