同步、异步、阻塞、非阻塞怎么理解?

在计算机世界中,IO是一个无处不在的概念,它是"输入/输出"的简称。简单来说,IO就是计算机与外部世界(例如硬件设备或网络)进行数据交换的过程。为了更好地理解IO,我们需要熟悉一些相关的概念,包括同步/异步和阻塞/非阻塞。这些概念看似复杂,但只要我们能理解他们之间的区别,就能够更好地理解IO的工作机制。

同步和异步概念 

同步和异步关注的是消息通信机制。

同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了。

异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果。

生活举例

同步:在人工咖啡店点咖啡,排队等待服务员制作完成,等制作完成之后,才能进行下一步行动。

异步:自助咖啡机等咖啡,可以在等咖啡时做其他事情,例如玩手机,读杂志。

同步的举例很明显现在已经被优化了,因为同步的对人为感觉明显不好,异步更为舒适。

阻塞和非阻塞概念

阻塞和非阻塞关注程序在等待调用结果时的状态。

阻塞:被调用者接受到任务请求,会挂起当前线程,执行任务请求,直到完成,然后返回给调用者。

非阻塞:被调用者,先做完其他的事情,然后开始做调用者的任务请求,不会阻塞当前线程。

生活举例

阻塞:交通拥堵的交通路口等待红绿灯,只有交通信号灯变绿才能继续前行,车辆被阻塞。

非阻塞:当你在等待电梯,此时电梯在其他楼层,采用非阻塞方式,可以采用楼梯代替电梯。

Java 代码举例

同步阻塞I/O(BIO)

import java.io.FileInputStream;
import java.io.IOException;

public class SyncBlockingIOExample {
    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("example.txt")) {
            int data;
            while ((data = fis.read()) != -1) {
                // 处理数据
                System.out.print((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
同步非阻塞I/O
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class SyncNonBlockingIOExample {
    public static void main(String[] args) throws Exception {
        FileChannel channel = FileChannel.open(Paths.get("example.txt"), StandardOpenOption.READ);
        ByteBuffer buffer = ByteBuffer.allocate(1024);

        while (channel.read(buffer) != -1) {
            buffer.flip();
            while (buffer.hasRemaining()) {
                // 处理数据
                System.out.print((char) buffer.get());
            }
            buffer.clear();
        }

        channel.close();
    }
}
异步I/O(AIO)
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.Future;

public class AsyncIOExample {
    public static void main(String[] args) throws Exception {
        AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths.get("example.txt"), StandardOpenOption.READ);
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        Future<Integer> result = channel.read(buffer, 0);

        while (!result.isDone()) {
            // 执行其他任务
        }

        buffer.flip();
        while (buffer.hasRemaining()) {
            // 处理数据
            System.out.print((char) buffer.get());
        }

        buffer.clear();
        channel.close();
    }
}

区别详解 

 同步I/O

1)定义:同步I/O是指程序发起一个I/O操作后,必须等待该操作完成并获取到结果后,才能继续执行后续代码。

2)特点:同步I/O操作会阻塞程序的执行,直到I/O操作完成。这意味着程序在等待I/O操作期间不能执行其他任务。

3)示例:在Java中,使用java.io包中的FileInputStreamFileOutputStream进行文件读写就是同步I/O的例子。

异步I/O

1)定义:异步I/O是指程序发起一个I/O操作后,不需要等待该操作完成,而是可以继续执行后续代码。I/O操作完成后,程序会通过回调、事件或轮询等方式得到通知。

2)特点:异步I/O不会阻塞程序的执行,允许程序在I/O操作进行的同时执行其他任务,提高了程序的并发性和效率。

3)示例:在Java中,使用java.nio.channels.AsynchronousFileChannel进行文件读写就是异步I/O的例子。

阻塞I/O

1)定义:阻塞I/O是指程序发起一个I/O操作后,如果数据尚未准备好(如数据未到达、文件未找到等),程序会一直等待,直到数据准备好并完成I/O操作。

2)特点:阻塞I/O会导致程序的执行线程被挂起,直到I/O操作完成。在这期间,线程不能执行其他任务。

3)示例:在Java中,使用java.io包中的Socket进行网络通信时,InputStream.read()方法就是阻塞I/O的例子。

非阻塞I/O

1)定义:非阻塞I/O是指程序发起一个I/O操作后,如果数据尚未准备好,I/O操作会立即返回一个错误或特定值,而不是等待数据准备好。

2)特点:非阻塞I/O允许程序在数据未准备好时继续执行其他任务,而不是等待。程序通常需要轮询或检查I/O操作的状态,以确定何时数据准备好。

3)示例:在Java中,使用java.nio包中的SocketChannel设置为非阻塞模式,并使用read()方法进行网络通信,就是非阻塞I/O的例子。

总结:

  • 同步IO和异步IO是根据程序等待IO操作完成的方式来区分的。

  • 阻塞IO和非阻塞IO是根据程序在等待IO操作完成时是否能继续执行其他操作来区分的。

  • 11
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值