Java IO等待案例

wen java案例 3

本文目录导读:

Java IO等待案例

  1. 传统阻塞IO(BIO)等待案例
  2. 阻塞文件读取
  3. 等待日志文件写入(模拟等待场景)
  4. NIO非阻塞与等待对比
  5. 模拟数据库查询等待
  6. 异步IO(AIOC)非阻塞演示
  7. 关键要点

我来通过几个典型的案例来说明Java IO等待的情况:

传统阻塞IO(BIO)等待案例

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class BioServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8080);
        System.out.println("服务器启动,等待客户端连接...");
        while (true) {
            // 这里会阻塞,等待客户端连接
            Socket socket = serverSocket.accept();
            System.out.println("客户端连接:" + socket.getRemoteSocketAddress());
            // 为每个客户端创建一个线程处理
            new Thread(() -> {
                try {
                    handleClient(socket);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
    private static void handleClient(Socket socket) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
        String line;
        while ((line = in.readLine()) != null) {
            System.out.println("收到消息:" + line);
            out.println("服务器响应:" + line.toUpperCase());
        }
    }
}

阻塞文件读取

import java.io.*;
import java.nio.charset.StandardCharsets;
public class BlockingFileRead {
    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        try (InputStream is = new FileInputStream("large_file.txt")) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            System.out.println("开始读取文件...");
            while ((bytesRead = is.read(buffer)) != -1) {
                // 模拟处理数据
                new String(buffer, 0, bytesRead, StandardCharsets.UTF_8);
                // 每个循环打印进度
                System.out.println("读取了 " + bytesRead + " 字节");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        long duration = System.currentTimeMillis() - startTime;
        System.out.println("文件读取完成,耗时:" + duration + "ms");
    }
}

等待日志文件写入(模拟等待场景)

import java.io.*;
import java.util.Random;
import java.util.concurrent.*;
public class IOWaitingDemo {
    private static final BlockingQueue<String> logQueue = new LinkedBlockingQueue<>();
    public static void main(String[] args) throws Exception {
        // 创建多个任务同时写入日志
        ExecutorService executor = Executors.newFixedThreadPool(3);
        System.out.println("开始并发写入日志...");
        long startTime = System.currentTimeMillis();
        // 创建3个写日志任务
        for (int i = 0; i < 3; i++) {
            final int taskId = i;
            executor.submit(() -> {
                try {
                    writeLog("日志任务-" + taskId);
                } catch (InterruptedException | IOException e) {
                    Thread.currentThread().interrupt();
                    e.printStackTrace();
                }
            });
        }
        executor.shutdown();
        executor.awaitTermination(30, TimeUnit.SECONDS);
        long duration = System.currentTimeMillis() - startTime;
        System.out.println("所有日志写入完成,总耗时:" + duration + "ms");
    }
    private static void writeLog(String taskName) throws InterruptedException, IOException {
        File logFile = new File("logs_" + taskName + ".log");
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(logFile))) {
            Random random = new Random();
            for (int i = 0; i < 10; i++) {
                // 模拟IO等待:随机延迟
                Thread.sleep(random.nextInt(500));
                writer.write("[" + taskName + "] 日志第" + (i+1) + "行: " + System.currentTimeMillis());
                writer.newLine();
                System.out.println(taskName + " 写入第 " + (i+1) + " 行日志");
            }
        }
    }
}

NIO非阻塞与等待对比

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Set;
public class NIOVsBIODemo {
    public static void main(String[] args) throws IOException {
        // NIO 非阻塞服务器
        ServerSocketChannel serverChannel = ServerSocketChannel.open();
        serverChannel.configureBlocking(false);  // 非阻塞模式
        serverChannel.bind(new InetSocketAddress(9090));
        Selector selector = Selector.open();
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("NIO服务器启动,等待连接...");
        while (true) {
            // 非阻塞地等待事件
            int readyChannels = selector.select(100);  // 最多等待100ms
            if (readyChannels == 0) {
                System.out.println("当前无连接请求,可以执行其他任务...");
                continue;
            }
            Set<SelectionKey> keys = selector.selectedKeys();
            for (SelectionKey key : keys) {
                if (key.isAcceptable()) {
                    // 接受连接
                    SocketChannel clientChannel = ((ServerSocketChannel) key.channel()).accept();
                    clientChannel.configureBlocking(false);
                    clientChannel.register(selector, SelectionKey.OP_READ);
                    System.out.println("接受新连接:" + clientChannel.getRemoteAddress());
                } else if (key.isReadable()) {
                    // 读取数据
                    SocketChannel clientChannel = (SocketChannel) key.channel();
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    int bytesRead = clientChannel.read(buffer);
                    if (bytesRead == -1) {
                        clientChannel.close();
                        key.cancel();
                    } else if (bytesRead > 0) {
                        String message = new String(buffer.array(), 0, bytesRead);
                        System.out.println("收到消息:" + message);
                        // 响应客户端
                        ByteBuffer response = ByteBuffer.wrap(("已收到: " + message).getBytes());
                        clientChannel.write(response);
                    }
                }
            }
            keys.clear();
        }
    }
}

模拟数据库查询等待

import java.util.concurrent.*;
import java.util.*;
public class DatabaseWaitingSimulation {
    private static final Map<String, Connection> connections = new ConcurrentHashMap<>();
    static class Connection {
        private boolean inUse = false;
        private int id;
        Connection(int id) {
            this.id = id;
        }
        synchronized boolean acquire() {
            if (!inUse) {
                inUse = true;
                return true;
            }
            return false;
        }
        synchronized void release() {
            inUse = false;
        }
        @Override
        public String toString() {
            return "Connection-" + id;
        }
    }
    public static void main(String[] args) throws Exception {
        // 初始化连接池
        for (int i = 1; i <= 3; i++) {
            connections.put("conn-" + i, new Connection(i));
        }
        ExecutorService executor = Executors.newFixedThreadPool(10);
        List<Future<String>> results = new ArrayList<>();
        System.out.println("模拟数据库并发查询...");
        // 创建10个并发查询任务
        for (int i = 0; i < 10; i++) {
            final int queryId = i;
            Future<String> future = executor.submit(() -> {
                return executeQuery(queryId);
            });
            results.add(future);
        }
        // 收集结果
        for (Future<String> future : results) {
            System.out.println(future.get());
        }
        executor.shutdown();
    }
    private static String executeQuery(int queryId) throws InterruptedException {
        System.out.println("查询 " + queryId + " 开始,等待连接池分配连接...");
        // 等待空闲连接
        Connection connection = null;
        long startWait = System.currentTimeMillis();
        while (connection == null) {
            // 尝试获取连接
            for (Connection conn : connections.values()) {
                if (conn.acquire()) {
                    connection = conn;
                    break;
                }
            }
            if (connection == null) {
                // 没有空闲连接,等待100ms后重试
                Thread.sleep(100);
                // 等待超时检查
                if (System.currentTimeMillis() - startWait > 2000) {
                    return "查询 " + queryId + " 等待超时";
                }
            }
        }
        try {
            // 模拟查询操作
            Thread.sleep(new Random().nextInt(300) + 100);
            String result = "查询 " + queryId + " 完成,使用连接: " + connection;
            return result;
        } finally {
            // 释放连接
            connection.release();
        }
    }
}

异步IO(AIOC)非阻塞演示

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.Future;
public class AsyncFileRead {
    public static void main(String[] args) throws Exception {
        Path path = Paths.get("async_data.txt");
        // 创建文件
        try (FileWriter writer = new FileWriter(path.toFile())) {
            for (int i = 0; i < 1000; i++) {
                writer.write(i + "\n");
            }
        }
        // 异步读取
        AsynchronousFileChannel channel = AsynchronousFileChannel.open(
            path, 
            StandardOpenOption.READ
        );
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        System.out.println("开始异步读取文件...");
        // 发起异步读取操作
        Future<Integer> result = channel.read(buffer, 0);
        // 异步读取期间可以执行其他任务
        System.out.println("文件正在读取中,执行其他任务...");
        Thread.sleep(1000);
        System.out.println("其他任务执行完成");
        // 等待读取完成
        int bytesRead = result.get();
        System.out.println("文件读取完成,共读取:" + bytesRead + " 字节");
        buffer.flip();
        String content = StandardCharsets.UTF_8.decode(buffer).toString();
        System.out.println("文件内容(前100字符):" + content.substring(0, Math.min(100, content.length())));
        channel.close();
    }
}

关键要点

  1. BIO(阻塞IO):每个IO操作会阻塞当前线程直到完成
  2. NIO(非阻塞IO):使用Selector实现多路复用,避免线程阻塞
  3. AIO(异步IO):通过Future或Callback实现真正的异步操作
  4. 连接池:解决数据库连接等资源的等待问题
  5. 线程池:避免频繁创建销毁线程造成的IO等待

这些案例展示了IO等待对性能的影响以及如何使用不同技术来优化,在实际应用中,应根据场景选择合适的IO模型。

抱歉,评论功能暂时关闭!