计算机底层技术学习之进程(或线程)调度-最合适类比的场景是医院就诊流程-挂号_开检查单_缴费_看检查结果_开药
Java NIO 核心概念 vs 医院系统映射
flowchart TB
    subgraph Java NIO
        Selector[Selector<br>分诊台]
        Channel[Channel<br>患者通道]
        Buffer[Buffer<br>病历本]
        SelectionKey[SelectionKey<br>就诊登记]
    end
    subgraph 医院系统
        分诊台[分诊台]
        患者通道[患者就诊通道]
        病历本[电子病历本]
        就诊登记[就诊登记卡]
    end
    Selector --> 分诊台
    Channel --> 患者通道
    Buffer --> 病历本
    SelectionKey --> 就诊登记
详细映射关系说明:
| Java NIO 组件 | 医院系统对应物 | 功能说明 | 
|---|---|---|
| Selector | 智能分诊台 | 监控所有患者状态,调度就绪的患者到对应科室 | 
| ServerSocketChannel | 医院挂号窗口 | 接收新患者连接(OP_ACCEPT) | 
| SocketChannel | 患者就诊通道 | 每个患者独立的诊疗通道(包含OP_READ/OP_WRITE状态) | 
| SelectionKey | 就诊登记卡 | 记录患者当前状态(挂号/待诊/检查中/取药中)和关联的诊疗档案 | 
| ByteBuffer | 电子病历本 | 存储患者症状描述和医生处方(通过flip()切换读写模式) | 
| OP_ACCEPT | 新患者到达 | 触发挂号流程 | 
| OP_READ | 患者描述症状 | 医生可读取患者信息 | 
| OP_WRITE | 开具处方 | 医生可向患者发送处方/检查单 | 
完整就诊流程代码实现
// 创建医院系统
Selector triageDesk = Selector.open(); // 智能分诊台
ServerSocketChannel registrationDesk = ServerSocketChannel.open(); // 挂号窗口
registrationDesk.bind(new InetSocketAddress(8080));
registrationDesk.configureBlocking(false);
registrationDesk.register(triageDesk, SelectionKey.OP_ACCEPT); // 监听新患者
while (true) {
    // 分诊台轮询(500ms超时)
    int readyPatients = triageDesk.select(500); 
    if (readyPatients == 0) continue;
    
    // 处理就绪患者
    Set<SelectionKey> activeCases = triageDesk.selectedKeys();
    Iterator<SelectionKey> caseIterator = activeCases.iterator();
    
    while (caseIterator.hasNext()) {
        SelectionKey caseKey = caseIterator.next();
        caseIterator.remove();
        
        if (caseKey.isAcceptable()) {
            // ======= 新患者挂号 =======
            SocketChannel patient = registrationDesk.accept();
            patient.configureBlocking(false);
            // 发放病历本(初始1024容量)
            ByteBuffer medicalRecord = ByteBuffer.allocate(1024); 
            // 登记到分诊台(初始关注读取症状)
            patient.register(triageDesk, SelectionKey.OP_READ, medicalRecord);
            
        } else if (caseKey.isReadable()) {
            // ======= 患者描述症状 =======
            SocketChannel patient = (SocketChannel) caseKey.channel();
            ByteBuffer record = (ByteBuffer) caseKey.attachment();
            
            int bytesRead = patient.read(record);
            if (bytesRead == -1) { // 患者离开
                patient.close();
                continue;
            }
            
            if (bytesRead > 0) {
                record.flip(); // 切换病历为读模式
                // 解析症状(实际业务处理)
                processSymptoms(record); 
                record.clear();
                
                // 变更状态:待开具处方
                caseKey.interestOps(SelectionKey.OP_WRITE);
            }
            
        } else if (caseKey.isWritable()) {
            // ======= 医生开具处方 =======
            SocketChannel patient = (SocketChannel) caseKey.channel();
            ByteBuffer record = (ByteBuffer) caseKey.attachment();
            
            // 生成处方(实际业务逻辑)
            String prescription = generatePrescription(); 
            record.put(prescription.getBytes());
            record.flip(); // 准备写模式
            
            // 发送处方
            while (record.hasRemaining()) {
                patient.write(record);
            }
            record.clear();
            
            // 变更状态:等待下次就诊
            caseKey.interestOps(SelectionKey.OP_READ);
        }
    }
}
// 症状处理方法
void processSymptoms(ByteBuffer record) {
    String symptoms = StandardCharsets.UTF_8.decode(record).toString();
    System.out.println("诊断症状: " + symptoms);
    // 这里可添加实际业务逻辑...
}
// 处方生成方法
String generatePrescription() {
    // 这里可添加实际业务逻辑...
    return "处方:\n- 维生素C 100mg/日\n- 休息3天";
}
关键流程解析
- 
挂号阶段 (OP_ACCEPT)
patient.register(triageDesk, SelectionKey.OP_READ, medicalRecord);- 新患者获得病历本(Buffer)
 - 初始关注"可读"状态(等待描述症状)
 
 - 
就诊阶段 (OP_READ)
patient.read(record); // 读取症状 record.flip(); // 切换为读模式 processSymptoms(record); // 业务处理 record.clear(); // 重置病历本 - 
处方阶段 (OP_WRITE)
record.put(prescription.getBytes()); // 写入处方 record.flip(); // 切换为写模式 patient.write(record); // 发送给患者 - 
状态转换
// 就诊完成 → 准备开处方 caseKey.interestOps(SelectionKey.OP_WRITE); // 处方完成 → 准备下次就诊 caseKey.interestOps(SelectionKey.OP_READ); 
高级优化技巧(资深开发者关注点)
- 
内存池优化
// 复用病历本(避免频繁创建) ByteBuffer record = ByteBuffer.allocateDirect(2048); // 堆外内存 - 
背压控制
// 当处方队列过长时暂停接收新症状 if (pendingPrescriptions > 100) { patient.register(triageDesk, 0); // 暂停所有事件 } - 
零拷贝化验单
// 检查报告直接传输(避免复制) FileChannel labReport = new FileInputStream("xray.jpg").getChannel(); labReport.transferTo(0, labReport.size(), patient); - 
急诊绿色通道
// 高优先级患者 patient.setOption(StandardSocketOptions.SO_PRIORITY, 10); 
这个映射体系展示了NIO如何像现代化医院一样,通过状态监控+资源复用+流程优化实现高效处理。Selector作为智能分诊台,避免医生(线程)空等;Buffer作为电子病历,避免数据反复拷贝;Channel作为独立就诊通道,保证诊疗过程隔离性。
                    
                
                
            
        
浙公网安备 33010602011771号