阻塞IO、非阻塞IO、异步IO的区别

1. 阻塞IO (Blocking IO)

在传统的阻塞IO模型中,示例中的 serverSocket.accept(),这是一个阻塞调用,意味着调用线程将被挂起直到一个连接请求到达。这是典型的阻塞行为。

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;public class BlockingIOServer {public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(8080);System.out.println("Server started on port 8080");while (true) {Socket clientSocket = serverSocket.accept();// 注意:accept() 是一个阻塞调用new Thread(() -> {try {byte[] buffer = new byte[1024];int bytesRead = clientSocket.getInputStream().read(buffer);// read() 也是一个阻塞调用if (bytesRead > 0) {String message = new String(buffer, 0, bytesRead);System.out.println("Received: " + message);}} catch (IOException e) {e.printStackTrace();} finally {try {clientSocket.close();} catch (IOException e) {e.printStackTrace();}}}).start();}}
}

2. 非阻塞IO (Non-Blocking IO)

在Java中,你可以使用 NIO(Non-blocking IO)库来实现非阻塞IO。例如,你使用 SelectorSelectableChannel 来监听多个 SocketChannel 的可读状态。当没有数据可读时,你的程序不会被阻塞,而是可以立即返回并处理其他任务,只有当数据真正到达时,你才会被通知去读取。

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;public class NonBlockingIOServer {public static void main(String[] args) throws IOException {Selector selector = Selector.open();ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.configureBlocking(false);serverSocketChannel.socket().bind(new InetSocketAddress(8080));serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);System.out.println("Server started on port 8080");while (true) {if (selector.select() == 0) {//这里会阻塞,等待Channel事件发生continue; // no events ready for processing}Set<SelectionKey> keys = selector.selectedKeys();Iterator<SelectionKey> iterator = keys.iterator();while (iterator.hasNext()) {SelectionKey key = iterator.next();iterator.remove();if (key.isAcceptable()) {ServerSocketChannel ssc = (ServerSocketChannel) key.channel();SocketChannel sc = ssc.accept();//这里是非阻塞sc.configureBlocking(false);sc.register(selector, SelectionKey.OP_READ);} else if (key.isReadable()) {SocketChannel sc = (SocketChannel) key.channel();ByteBuffer buffer = ByteBuffer.allocate(1024);int bytesRead = sc.read(buffer);//这里也是非阻塞if (bytesRead > 0) {buffer.flip();byte[] data = new byte[buffer.remaining()];buffer.get(data);System.out.println("Received: " + new String(data));}}}}}
}

在这个示例中,selector.select()serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT) 结合使用。serverSocketChannel 已经配置为非阻塞模式,这意味着 serverSocketChannel.accept() 本身不会阻塞当前线程。然而,selector.select() 方法是一个阻塞调用,它会阻塞直到至少一个通道上的事件准备好被处理。当调用 selector.select() 时,线程将等待至少一个注册的通道有事件发生(例如,一个连接请求到达或数据可读)。 

3. 异步IO (Asynchronous IO)

异步IO是最先进的IO模型,它不仅不会阻塞线程,而且还会在IO操作完成后主动通知应用程序。也就是说,你只需要告诉操作系统你想做什么,然后继续执行其他任务,当IO操作完成时,操作系统会通过回调函数、事件通知等方式告知你。

示例:

在这个示例中,serverChannel.accept() 是异步调用,它使用了 CompletionHandler。这意味着调用线程不会被阻塞,而是会立即返回。当一个连接请求到达时,CompletionHandlercompleted 方法将在异步线程池中的某个线程上被调用。因此,serverChannel.accept(null, new CompletionHandler<...>) 在调用时不会阻塞当前线程。

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class AsyncIOServer {public static void main(String[] args) throws IOException {ExecutorService threadPool = Executors.newFixedThreadPool(5);AsynchronousChannelGroup group = AsynchronousChannelGroup.withThreadPool(threadPool);AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open(group).bind(new java.net.InetSocketAddress(8080));System.out.println("Server started on port 8080");serverChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {@Overridepublic void completed(AsynchronousSocketChannel result, Void attachment) {ByteBuffer buffer = ByteBuffer.allocate(1024);result.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {@Overridepublic void completed(Integer result, ByteBuffer attachment) {if (result > 0) {attachment.flip();byte[] data = new byte[attachment.remaining()];attachment.get(data);System.out.println("Received: " + new String(data));attachment.clear();result.read(attachment, attachment, this);} else {result.close();}}@Overridepublic void failed(Throwable exc, ByteBuffer attachment) {exc.printStackTrace();}});serverChannel.accept(null, this);}@Overridepublic void failed(Throwable exc, Void attachment) {exc.printStackTrace();}});}
}

总结一下,阻塞IO会阻止线程直到IO操作完成;非阻塞IO允许线程在没有数据可处理时立即返回;而异步IO则完全不需要线程等待,而是通过回调或事件通知来处理完成的IO操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/34773.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ARM-V9 RME(Realm Management Extension)系统架构之系统初始化流程

安全之安全(security)博客目录导读 目录 一、重置取消 二、应用处理单元&#xff08;PE&#xff09;初始启动 三、MSD初始化 四、GPT初始化 五、初始启动退出&#xff08;由所有应用PE执行&#xff09; 六、RMSD初始化 七、PE进入丢失上下文的低功耗状态 本博客提供了R…

uniapp H5端使用百度地图

1、登录百度地图开放平台 https://lbsyun.baidu.com/&#xff08;没有账号则先去创建一个百度账号&#xff09; 2、进入百度地图开放平台控制台&#xff08;导航栏“控制台”&#xff09;&#xff0c;点击“应用管理”-“我的应用” 3、选择“创建应用”&#xff0c;应用模块选…

msvcr110.dll丢失的解决方法,亲测有效的几种解决方法

最近&#xff0c;我在启动一个程序时&#xff0c;系统突然弹出一个错误提示&#xff0c;告诉我电脑缺失了一个名为msvcr110.dll的文件。这让我感到非常困惑&#xff0c;因为我之前从未遇到过这样的问题。经过一番搜索和尝试&#xff0c;我总结了5种靠谱的解决方法。下面分享给大…

C# 静态类中构造、字段和属性等的执行顺序,含有单例模式分析

C# 静态类时我们实战项目开发中用的非常多的。有些时候可能他的执行顺序并非如我们认为的那样&#xff0c;那就快速来看一下吧&#xff01; 在C#中&#xff0c;静态类的构造函数是在第一次访问该类的任何成员时执行的。静态构造函数是不可继承的&#xff0c;并且在访问静态类的…

百日筑基第三天-SOA初步了解

百日筑基第三天-SOA初步了解 SOA&#xff08;Service-Oriented Architecture&#xff0c;面向服务的架构&#xff09;是一种软件设计原则&#xff0c;它倡导将应用程序分解为独立的服务单元&#xff0c;这些服务通过定义良好的接口相互通信&#xff0c;以实现业务功能。而RPC&…

高效运维:标准化与智能化的运维流程管理实践

高效运维&#xff1a;标准化与智能化的运维流程管理实践 在信息化建设日益深化的今天&#xff0c;运维流程管理已成为企业确保其信息系统稳定、高效运行的关键手段。通过系统化、标准化的运维流程管理&#xff0c;企业能够有效预防系统故障&#xff0c;提升服务质量&#xff0…

7. Revit API UI: ExternalEvent(外部事件)

7. Revit API UI: ExternalEvent&#xff08;外部事件&#xff09; 接着上一篇&#xff0c;上一篇中&#xff0c;我们简单讲了下预览控件&#xff0c;并给了示例。 示例中&#xff0c;通过点击按钮&#xff0c;删除楼板模型&#xff0c;这是怎么做到的呢&#xff1f;这就得用…

React的路由(ReactRouter)-路由导航跳转

1.第一步 // createBrowserRouter路由 RouterProvider组件 import {createBrowserRouter,RouterProvider} from react-router-dom // 创建router实例对象&#xff0c;并配置路由对应关系 const routercreateBrowserRouter([{path:/login,element:<div>我是登录页</di…

vue3-登录小案例(借助ElementPlus+axios)

1.创建一个vue3的项目。 npm create vuelatest 2.引入Elementplus组件库 链接&#xff1a;安装 | Element Plus npm install element-plus --save 在main.js中引入 import ElementPlus from "element-plus";import "element-plus/dist/index.css";ap…

【Android】Android中继承Activity、Application和AppCompatActivity的区别

在 Android 开发中&#xff0c;Activity、Application 和 AppCompatActivity 是三个重要的类&#xff0c;它们各自有不同的作用和用途&#xff1a; 1. Activity Activity 是 Android 应用中的一个核心组件&#xff0c;代表了用户界面上的一个单一屏幕或交互界面。每个 Activi…

python--序列化模块json与pickle

什么叫序列化&#xff1f; 将原本的字典、列表等内容转换成一个字符串的过程就 叫做序列化。 多用的两个序列化模块&#xff1a;json与pickle json&#xff0c;用于字符串 和 python数据类型间进行转换 pickle&#xff0c;用于python特有的类型 和 python的数据类型间进行转换 …

在 Debian 系统上安装 `make` 并且编译安装 Python 3.9

在 Debian 系统上安装 make 工具和 Python 3.9 1. 准备工作 首先&#xff0c;确保你的系统已经更新到最新的软件包列表&#xff1a; sudo apt update2. 安装 make 工具 make 工具可以通过以下命令来安装&#xff1a; sudo apt install make安装完成后&#xff0c;你可以使…

Scania斯堪尼亚SHL题库综合能力性格测试真题题型解析及面试经验

一、走进Scania斯堪尼亚 Scania是一家成立于1891年的瑞典公司&#xff0c;专注于重型卡车和巴士的制造&#xff0c;以其模块化系统和环保设计闻名。作为全球领先的运输解决方案提供商&#xff0c;Scania不仅提供高质量的车辆&#xff0c;还提供相关服务和融资解决方案。公司秉…

Ruby langchainrb gem and custom configuration for the model setup

题意&#xff1a;Ruby 的 langchainrb gem 以及针对模型设置的自定义配置 问题背景&#xff1a; I am working in a prototype using the gem langchainrb. I am using the module assistant module to implemente a basic RAG architecture. 我正在使用 langchainrb 这个 ge…

Beautiful Soup的使用

1、Beautiful Soup简介 Beautiful Soup是一个Python的一个HTML或XML的解析库&#xff0c;我们用它可以方便地从网页中提取数据。 Beautiful Soup 提供一些简单的、Python 式的函数来处理导航、搜索、修改分析树等功能。它是一个工具箱&#xff0c;通过解析文档为用户提供需要抓…

java线程间的通信- notify和 wait

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 一…

JDBC中的事务及其ACID特性

在JDBC&#xff08;Java Database Connectivity&#xff09;中&#xff0c;事务&#xff08;Transaction&#xff09;是指作为单个逻辑工作单元执行的一系列操作。这些操作要么全部执行&#xff0c;要么全部不执行&#xff0c;从而确保数据库的完整性和一致性。事务是现代数据库…

实战|记一次java协同办公OA系统源码审计

前言 因为笔者也是代码审计初学者&#xff0c;写得不好的地方请见谅。该文章是以项目实战角度出发&#xff0c;希望能给大家带来启发。 审计过程 审计思路 1、拿到一个项目首先要看它使用了什么技术框架&#xff0c;是使用了ssh框架&#xff0c;还是使用了ssm框架&#xff…

面试突击指南:Java基础面试题2

面向对象和集合 1. 面向对象和面向过程的区别 面向过程:面向过程的编程方式是分析解决问题的步骤,然后用函数把这些步骤一步一步地实现,并在使用的时候逐个调用。这种方式性能较高,因此在单片机和嵌入式开发中经常采用面向过程开发。 面向对象:面向对象的编程方式是把问…

C#基于SkiaSharp实现印章管理(2)

上一篇文章最后提到基于System.Text.Json能够序列化SKColor对象&#xff0c;但是反序列化时却无法解析本地json数据。换成Newtonsoft.Json进行序列化和反序列化也是类似的问题。   通过百度及查看微软的帮助文档&#xff0c;上述情况下需自定义转换类以处理SKColor类型数据的…