当前位置: 首页 > news >正文

Java提供了哪些IO方式? NIO如何实现多路复用?

第11讲 | Java提供了哪些IO方式? NIO如何实现多路复用?

在这里插入图片描述

IO 一直是软件开发中的核心部分之一,伴随着海量数据增长和分布式系统的发展,IO 扩展能力愈发重要。幸运的是,Java 平台 IO 机制经过不断完善,虽然在某些方面仍有不足,但已经在实践中证明了其构建高扩展性应用的能力。

今天我要问你的问题是,Java 提供了哪些 IO 方式? NIO 如何实现多路复用?

典型回答

Java IO 方式有很多种,基于不同的 IO 抽象模型和交互方式,可以进行简单区分。

第一,传统的 java.io 包,它基于流模型实现,提供了我们最熟知的一些 IO 功能,比如 File 抽象、输入输出流等。交互方式是同步、阻塞的方式,也就是说,在读取输入流或者写入输出流时,在读、写动作完成之前,线程会一直阻塞在那里,它们之间的调用是可靠的线性顺序。

java.io 包的好处是代码比较简单、直观,缺点则是 IO 效率和扩展性存在局限性,容易成为应用性能的瓶颈。

很多时候,人们也把 java.net 下面提供的部分网络 API,比如 Socket、ServerSocket、HttpURLConnection 也归类到同步阻塞 IO 类库,因为网络通信同样是 IO 行为。

第二,在 Java 1.4 中引入了 NIO 框架(java.nio 包),提供了 Channel、Selector、Buffer 等新的抽象,可以构建多路复用的、同步非阻塞 IO 程序,同时提供了更接近操作系统底层的高性能数据操作方式。

第三,在 Java 7 中,NIO 有了进一步的改进,也就是 NIO 2,引入了异步非阻塞 IO 方式,也有很多人叫它 AIO(Asynchronous IO)。异步 IO 操作基于事件和回调机制,可以简单理解为,应用操作直接返回,而不会阻塞在那里,当后台处理完成,操作系统会通知相应线程进行后续工作。

考点分析

我上面列出的回答是基于一种常见分类方式,即所谓的 BIO、NIO、NIO 2(AIO)。

在实际面试中,从传统 IO 到 NIO、NIO 2,其中有很多地方可以扩展开来,考察点涉及方方面面,比如:

基础 API 功能与设计, InputStream/OutputStream 和 Reader/Writer 的关系和区别。

NIO、NIO 2 的基本组成。

给定场景,分别用不同模型实现,分析 BIO、NIO 等模式的设计和实现原理。

NIO 提供的高性能数据操作方式是基于什么原理,如何使用?

或者,从开发者的角度来看,你觉得 NIO 自身实现存在哪些问题?有什么改进的想法吗?

IO 的内容比较多,专栏一讲很难能够说清楚。IO 不仅仅是多路复用,NIO 2 也不仅仅是异步 IO,尤其是数据操作部分,会在专栏下一讲详细分析。

知识扩展

首先,需要澄清一些基本概念:

区分同步或异步(synchronous/asynchronous)。简单来说,同步是一种可靠的有序运行机制,当我们进行同步操作时,后续的任务是等待当前调用返回,才会进行下一步;而异步则相反,其他任务不需要等待当前调用返回,通常依靠事件、回调等机制来实现任务间次序关系。

区分阻塞与非阻塞(blocking/non-blocking)。在进行阻塞操作时,当前线程会处于阻塞状态,无法从事其他任务,只有当条件就绪才能继续,比如 ServerSocket 新连接建立完毕,或数据读取、写入操作完成;而非阻塞则是不管 IO 操作是否结束,直接返回,相应操作在后台继续处理。

不能一概而论认为同步或阻塞就是低效,具体还要看应用和系统特征。

对于 java.io,我们都非常熟悉,我这里就从总体上进行一下总结,如果需要学习更加具体的操作,你可以通过教程等途径完成。总体上,我认为你至少需要理解一下内容。

IO 不仅仅是对文件的操作,网络编程中,比如 Socket 通信,都是典型的 IO 操作目标。

输入流、输出流(InputStream/OutputStream)是用于读取或写入字节的,例如操作图片文件。

而 Reader/Writer 则是用于操作字符,增加了字符编解码等功能,适用于类似从文件中读取或者写入文本信息。本质上计算机操作的都是字节,不管是网络通信还是文件读取,Reader/Writer 相当于构建了应用逻辑和原始数据之间的桥梁。

BufferedOutputStream 等带缓冲区的实现,可以避免频繁的磁盘读写,进而提高 IO 处理效率。这种设计利用了缓冲区,将批量数据进行一次操作,但在使用中千万别忘了 flush。

参考下面这张类图,很多 IO 工具类都实现了 Closeable 接口,因为需要进行资源的释放。比如,打开 FileInputStream,它就会获取相应的文件描述符(FileDescriptor),需要利用 try-with-resources、 try-finally 等机制保证 FileInputStream 被明确关闭,进而相应文件描述符也会失效,否则将导致资源无法被释放。利用专栏前面的内容提到的 Cleaner 或 finalize 机制作为资源释放的最后把关,也是必要的。

下面是我整理的一个简化版的类图,阐述了日常开发应用较多的类型和结构关系。

在这里插入图片描述

  1. Java NIO 概览

    首先,熟悉一下 NIO 的主要组成部分:

    Buffer,高效的数据容器,除了布尔类型,所有原始数据类型都有相应的 Buffer 实现。

    Channel,类似在 Linux 之类操作系统上看到的文件描述符,是 NIO 中被用来支持批量式 IO 操作的一种抽象。

    File 或者 Socket,通常被认为是比较高层次的抽象,而 Channel 则是更加操作系统底层的一种抽象,这也使得 NIO 得以充分利用现代操作系统底层机制,获得特定场景的性能优化,例如,DMA(Direct Memory Access)等。不同层次的抽象是相互关联的,我们可以通过 Socket 获取 Channel,反之亦然。

    Selector,是 NIO 实现多路复用的基础,它提供了一种高效的机制,可以检测到注册在 Selector 上的多个 Channel 中,是否有 Channel 处于就绪状态,进而实现了单线程对多 Channel 的高效管理。Selector 同样是基于底层操作系统机制,不同模式、不同版本都存在区别,例如,在最新的代码库里,相关实现如下:

Charset,提供 Unicode 字符串定义,NIO 也提供了相应的编解码器等,例如,通过下面的方式进行字符串到 ByteBuffer 的转换:

Charset.defaultCharset().encode("Hello world!"));
  1. NIO 能解决什么问题?

    下面我通过一个典型场景,来分析为什么需要 NIO,为什么需要多路复用。设想,我们需要实现一个服务器应用,只简单要求能够同时服务多个客户端请求即可。

    使用 java.io 和 java.net 中的同步、阻塞式 API,可以简单实现。

    
    public class DemoServer extends Thread {private ServerSocket serverSocket;public int getPort() {return  serverSocket.getLocalPort();}public void run() {try {serverSocket = new ServerSocket(0);while (true) {Socket socket = serverSocket.accept();RequestHandler requestHandler = new RequestHandler(socket);requestHandler.start();}} catch (IOException e) {e.printStackTrace();} finally {if (serverSocket != null) {try {serverSocket.close();} catch (IOException e) {e.printStackTrace();};}}}public static void main(String[] args) throws IOException {DemoServer server = new DemoServer();server.start();try (Socket client = new Socket(InetAddress.getLocalHost(), server.getPort())) {BufferedReader bufferedReader = new BufferedReader(new                   InputStreamReader(client.getInputStream()));bufferedReader.lines().forEach(s -> System.out.println(s));}}}
    // 简化实现,不做读取,直接发送字符串
    class RequestHandler extends Thread {private Socket socket;RequestHandler(Socket socket) {this.socket = socket;}@Overridepublic void run() {try (PrintWriter out = new PrintWriter(socket.getOutputStream());) {out.println("Hello world!");out.flush();} catch (Exception e) {e.printStackTrace();}}}

    其实现要点是:

    服务器端启动 ServerSocket,端口 0 表示自动绑定一个空闲端口。

    调用 accept 方法,阻塞等待客户端连接。

    利用 Socket 模拟了一个简单的客户端,只进行连接、读取、打印。

    当连接建立后,启动一个单独线程负责回复客户端请求。

    这样,一个简单的 Socket 服务器就被实现出来了。

思考一下,这个解决方案在扩展性方面,可能存在什么潜在问题呢?

大家知道 Java 语言目前的线程实现是比较重量级的,启动或者销毁一个线程是有明显开销的,每个线程都有单独的线程栈等结构,需要占用非常明显的内存,所以,每一个 Client 启动一个线程似乎都有些浪费。

那么,稍微修正一下这个问题,我们引入线程池机制来避免浪费。


serverSocket = new ServerSocket(0);
executor = Executors.newFixedThreadPool(8);while (true) {Socket socket = serverSocket.accept();RequestHandler requestHandler = new RequestHandler(socket);executor.execute(requestHandler);
}

这样做似乎好了很多,通过一个固定大小的线程池,来负责管理工作线程,避免频繁创建、销毁线程的开销,这是我们构建并发服务的典型方式。这种工作方式,可以参考下图来理解。

在这里插入图片描述

如果连接数并不是非常多,只有最多几百个连接的普通应用,这种模式往往可以工作的很好。但是,如果连接数量急剧上升,这种实现方式就无法很好地工作了,因为线程上下文切换开销会在高并发时变得很明显,这是同步阻塞方式的低扩展性劣势。

NIO 引入的多路复用机制,提供了另外一种思路,请参考我下面提供的新的版本。


public class NIOServer extends Thread {public void run() {try (Selector selector = Selector.open();ServerSocketChannel serverSocket = ServerSocketChannel.open();) {// 创建Selector和ChannelserverSocket.bind(new InetSocketAddress(InetAddress.getLocalHost(), 8888));serverSocket.configureBlocking(false);// 注册到Selector,并说明关注点serverSocket.register(selector, SelectionKey.OP_ACCEPT);while (true) {selector.select();// 阻塞等待就绪的Channel,这是关键点之一Set<SelectionKey> selectedKeys = selector.selectedKeys();Iterator<SelectionKey> iter = selectedKeys.iterator();while (iter.hasNext()) {SelectionKey key = iter.next();// 生产系统中一般会额外进行就绪状态检查sayHelloWorld((ServerSocketChannel) key.channel());iter.remove();}}} catch (IOException e) {e.printStackTrace();}}private void sayHelloWorld(ServerSocketChannel server) throws IOException {try (SocketChannel client = server.accept();) {          client.write(Charset.defaultCharset().encode("Hello world!"));}}// 省略了与前面类似的main
}

这个非常精简的样例掀开了 NIO 多路复用的面纱,我们可以分析下主要步骤和元素:

首先,通过 Selector.open() 创建一个 Selector,作为类似调度员的角色。

然后,创建一个 ServerSocketChannel,并且向 Selector 注册,通过指定 SelectionKey.OP_ACCEPT,告诉调度员,它关注的是新的连接请求。注意,为什么我们要明确配置非阻塞模式呢?这是因为阻塞模式下,注册操作是不允许的,会抛出 IllegalBlockingModeException 异常。

Selector 阻塞在 select 操作,当有 Channel 发生接入请求,就会被唤醒。

在 sayHelloWorld 方法中,通过 SocketChannel 和 Buffer 进行数据操作,在本例中是发送了一段字符串。

可以看到,在前面两个样例中,IO 都是同步阻塞模式,所以需要多线程以实现多任务处理。而 NIO 则是利用了单线程轮询事件的机制,通过高效地定位就绪的 Channel,来决定做什么,仅仅 select 阶段是阻塞的,可以有效避免大量客户端连接时,频繁线程切换带来的问题,应用的扩展能力有了非常大的提高。下面这张图对这种实现思路进行了形象地说明。

在 Java 7 引入的 NIO 2 中,又增添了一种额外的异步 IO 模式,利用事件和回调,处理 Accept、Read 等操作。 AIO 实现看起来是类似这样子:


AsynchronousServerSocketChannel serverSock =        AsynchronousServerSocketChannel.open().bind(sockAddr);
serverSock.accept(serverSock, new CompletionHandler<>() { //为异步操作指定CompletionHandler回调函数@Overridepublic void completed(AsynchronousSocketChannel sockChannel, AsynchronousServerSocketChannel serverSock) {serverSock.accept(serverSock, this);// 另外一个 write(sock,CompletionHandler{})sayHelloWorld(sockChannel, Charset.defaultCharset().encode("Hello World!"));}// 省略其他路径处理方法...
});

鉴于其编程要素(如 Future、CompletionHandler 等),我们还没有进行准备工作,为避免理解困难,我会在专栏后面相关概念补充后的再进行介绍,尤其是 Reactor、Proactor 模式等方面将在 Netty 主题一起分析,这里我先进行概念性的对比:

基本抽象很相似,AsynchronousServerSocketChannel 对应于上面例子中的 ServerSocketChannel;AsynchronousSocketChannel 则对应 SocketChannel。

业务逻辑的关键在于,通过指定 CompletionHandler 回调接口,在 accept/read/write 等关键节点,通过事件机制调用,这是非常不同的一种编程思路。

今天我初步对 Java 提供的 IO 机制进行了介绍,概要地分析了传统同步 IO 和 NIO 的主要组成,并根据典型场景,通过不同的 IO 模式进行了实现与拆解。专栏下一讲,我还将继续分析 Java IO 的主题。

一课一练

关于今天我们讨论的题目你做到心中有数了吗?留一道思考题给你,NIO 多路复用的局限性是什么呢?你遇到过相关的问题吗?

请你在留言区写写你对这个问题的思考,我会选出经过认真思考的留言,送给你一份学习鼓励金,欢迎你与我一起讨论。

业务逻辑的关键在于,通过指定 CompletionHandler 回调接口,在 accept/read/write 等关键节点,通过事件机制调用,这是非常不同的一种编程思路。

今天我初步对 Java 提供的 IO 机制进行了介绍,概要地分析了传统同步 IO 和 NIO 的主要组成,并根据典型场景,通过不同的 IO 模式进行了实现与拆解。专栏下一讲,我还将继续分析 Java IO 的主题。

一课一练

关于今天我们讨论的题目你做到心中有数了吗?留一道思考题给你,NIO 多路复用的局限性是什么呢?你遇到过相关的问题吗?

请你在留言区写写你对这个问题的思考,我会选出经过认真思考的留言,送给你一份学习鼓励金,欢迎你与我一起讨论。

你的朋友是不是也在准备面试呢?你可以“请朋友读”,把今天的题目分享给好友,或许你能帮到他。

相关文章:

Java提供了哪些IO方式? NIO如何实现多路复用?

第11讲 | Java提供了哪些IO方式&#xff1f; NIO如何实现多路复用&#xff1f; IO 一直是软件开发中的核心部分之一&#xff0c;伴随着海量数据增长和分布式系统的发展&#xff0c;IO 扩展能力愈发重要。幸运的是&#xff0c;Java 平台 IO 机制经过不断完善&#xff0c;虽然在某…...

人的大脑遇事的思考解决过程

人遇到问题的思考解决过程&#xff0c;大概如下&#xff1a;1&#xff09; 遇到问题&#xff1b;2&#xff09; 首先&#xff0c;不是直接推理&#xff0c;而是用直觉在自己的知识模式库里搜索&#xff0c;有没有相似的模式或者相同的模式。3&#xff09; 如果&#xff1a;3a)有…...

GNU zlib 压缩与解压文件详细介绍

GNU zlib 压缩与解压文件详细介绍 1.概述 zlib 模块为 GNU 项目的 zlib 压缩库中的许多函数提供了一个低级接口 2.使用内存数据压缩与解压 2.1.压缩与解压缩 使用 zlib 的最简单方法是将所有数据保存在内存中进行压缩或解压缩。 import zlib import binasciioriginal_dat…...

离线环境轻量级自动化部署

流程图&#xff1a; 常规系统发布的痛点 服务器频繁重启&#xff0c;上面部署的应用服务不能随之重启&#xff0c;导致服务时常宕机应用手动部署相对比较麻烦&#xff0c;步骤繁琐应用发布环境取决于发布人本地环境&#xff0c;导致不同发布人每次发布环境不一致&#xff0c;导…...

In-context Learning

formulate the example query -> LLM -> answerno gradient descent and fine-tuning, no parameters updateadvantages: 提供了与LLM进行交流的可解释的接口&#xff0c;通过template和demonstration将人类知识和LLM更好的结合&#xff1b;更像人类的预测思维&#xff…...

【新2023】华为OD机试 - 最优调度策略(Python)

华为 OD 清单查看地址:blog.csdn.net/hihell/category_12199275.html 最优调度策略 题目 在通信系统中有一个常见的问题是对用户进行不同策略的调度 会得到不同系统消耗的性能 假设由 N 个待串行用户,每个用户可以使用 A/B/C 三种不同的调度策略 不同的策略会消耗不同的系…...

Python列表系列之统计计算

Python也提供了一些内置函数去实现诸如统计、计算的功能&#xff0c;下面我们具体来看一下 基本语法 1、获取元素出现的次数 使用列表的count()方法可以获取元素在列表中出现的次数&#xff0c;语法格式如下&#xff1a; listname.count(obj) lisetname&#xff1a;列表的名…...

【蓝桥杯集训·每日一题】AcWing 1460. 我在哪?

文章目录一、题目1、原题链接2、题目描述二、解题报告1、思路分析2、时间复杂度3、代码详解三、知识风暴二分查找哈希表一、题目 1、原题链接 1460. 我在哪&#xff1f; 2、题目描述 农夫约翰出门沿着马路散步&#xff0c;但是他现在发现自己可能迷路了&#xff01; 沿路有一…...

一个不可忽视的重要能力

阅读本文大概需要 2.16 分钟。1、自我们开工后&#xff0c;年后第一场直播&#xff0c;场观二十万出头&#xff0c;以为是不是巧合还是卡 bug 了&#xff0c;就最近又测了下&#xff0c;发现连续几场直播下来&#xff0c;场观数据依旧很吓人&#xff0c;都是十几二十万&#xf…...

2023.2.6-2.12 AI行业周刊(第136期):住院

周末把父亲送到医院&#xff0c;安顿下来&#xff0c;这周还是决定做膝关节的手术了。 一辈子长期的劳累&#xff0c;加上前两年搬家时的辛苦&#xff0c;最终导致膝关节受损严重。 这两年来&#xff0c;走路每一步都很疼&#xff0c;纠结了很久&#xff0c;去了上海&#xf…...

听说2年以上的自动化测试都有16k+,4年10k的你还要等待奇迹吗?

个人简介学渣一枚&#xff0c;2017年6月某xx学校毕业。从事自动化测试已经4年&#xff0c;。2018年的时候&#xff0c;由于项目的原因&#xff0c;开始使用Robot Framework测试框架&#xff0c;正因为有Python的基础所以很快就理解了Robot Framework框架的工作原理&#xff0c;…...

git 命令实战

大家好&#xff0c;我是 17。 今天和大家一起用前面学过的命令做过实践。 git 命令实战 你在分支 A,一个同事在分支 B fix 了一个bug。你不方便 merge 分支B,只想更新这个 fix bug 的提交。 最先想到的是 cherry-pick&#xff0c;但还有两个办法&#xff0c;git restore&am…...

基于机器学习LSTM的古代汉语切分标注算法及语料库研究 完整代码+数据+论文

完整代码&#xff1a;https://download.csdn.net/download/qq_38735017/87382302摘 要近年来&#xff0c;深度学习的浪潮渗透在科研和生活领域的方方面面&#xff0c;本文主要研究深度学习在自然语言处理&#xff0c;尤其是古汉语自然语言处理方面的应用。本文旨在利用计算机帮…...

魔百和M401A刷入Armbian系统EMMC开启wifi

文章目录一、Armbian系统写入U盘二、U盘内uEnv.txt文件修改三、盒子从U盘进行启动四、设置用户名和密码五、Armbian系统写入EMMC六、 重启系统reboot(不可以拔U盘)七、盒子关机拔出U盘八、插入USB无线网卡&#xff0c;连接wifi上次盒子刷了5.15版本的armbian系统&#xff0c;可…...

超实用的小红书内容营销策略分享!纯干货

抓住小红书内容流量密码就是掌握了财富&#xff0c;越来越多的品牌方和商家都在小红书上收获了相当可观的用户流量&#xff0c;如果你的小红书营销没有什么起色&#xff0c;那绝对是没有走对方向。 小红书是一个内容为王的平台&#xff0c;如果你还不懂下面这些小红书内容营销…...

高压放大器在介电泳效应的细胞分选研究中的应用

实验名称&#xff1a;高压放大器在介电泳效应的细胞分选研究中的应用研究方向&#xff1a;生物医学测试目的&#xff1a;细胞分选在分析化学和生物医药领域有着非常重要的应用。在众多的分选方法中&#xff0c;微流控分选方法以其响应速度快、样品需求少等优点成为研究热门。微…...

Redis三 高级篇-3. 最佳实践

《Redis三 高级篇-3. 最佳实践》 提示: 本材料只做个人学习参考,不作为系统的学习流程,请注意识别!!! 《Redis三 高级篇-3. 最佳实践》《Redis三 高级篇-3. 最佳实践》1、Redis键值设计1.1、优雅的key结构1.2、拒绝BigKey1.2.1、BigKey的危害1.2.2、如何发现BigKey①redis-cli…...

基于 VPX 总线的工件台运动控制系统研究与开发-以光刻运动台为例(一)

工件台系统是光刻机的关键子系统之一&#xff0c;工件台运动控制系统对实现光刻机性能指标具有至关重要的作用&#xff0c;因此研发工件台运动控制系统具有极其重要的工程应用价值。论文根据工件台控制系统必须具备的并行性、同步性和实时性等技术需求&#xff0c;建立了基于 V…...

回溯算法理论基础

目录什么是回溯法回溯法的效率回溯法解决的问题如何理解回溯法回溯法模板什么是回溯法 回溯法也可以叫做回溯搜索法&#xff0c;它是一种搜索的方式。 回溯是递归的副产品&#xff0c;只要有递归就会有回溯。 所以以下讲解中&#xff0c;回溯函数也就是递归函数&#xff0c;指…...

【STM32笔记】低功耗模式下GPIO省电配置避坑实验(闲置引脚配置为模拟输入其实更耗电)

【STM32笔记】低功耗模式下GPIO省电配置避坑实验&#xff08;闲置引脚配置为模拟输入其实更耗电&#xff09; 前文&#xff1a; blog.csdn.net/weixin_53403301/article/details/128216064 【STM32笔记】HAL库低功耗模式配置&#xff08;ADC唤醒无法使用、低功耗模式无法烧录解…...

AI算法创新赛-人车目标检测竞赛总结02

源码目录--AI0000026/ --models/ #存放原始模型文件 --scripts/ #存放模型编译、量化所用到的命令脚本&#xff0c;标签格式转换的脚本。 --data/ #存放B榜数据集102张图片 --bmodel/ #存放编译或量化生成的xxx.bmodel --test/ #存放执行推理的代码&#xff0c;会调用bmodel/中…...

Python 编程必备:盘点nginx和gunicorn的几大用法,建议收藏

程序员是新兴技术工种中比较高薪的一个&#xff0c;在互联网公司&#xff0c;程序员往往与秃头&#xff0c;压力大&#xff0c;找不到女朋友等等挂钩。 最近&#xff0c;最新技能类榜单出炉&#xff0c;这是一个关于程序员自己给自己贴的几个标签。 其中&#xff0c;不难看出…...

USB3.0移动硬盘启动Win7的方法(AHCI/AMD USB3.0/Win7)

古董电脑(intel处理器&#xff0c;无USB3.0接口)突然坏了&#xff0c;已经没有维修价值了&#xff0c;硬盘还是完好的。欲把硬盘拆下来&#xff0c;装到USB3.0硬盘盒上&#xff0c;然后在新电脑(AMD R5-4650G/A520)上从USB3.0硬盘盒上启动。 一、需要工具 SATA数据线PS/2鼠标…...

Python学习-----函数3.0(嵌套函数、闭包、装饰器)

目录 1.函数嵌套 2.闭包 3.装饰器 这一节&#xff0c;我会详细Python中讲解函数的进阶内容&#xff0c;包括嵌套函数、闭包和装饰器。一起来学习吧&#xff01;&#xff01;&#xff01; 1.函数嵌套 概念&#xff1a;函数里面再定义一个函数 作用&#xff1a;当我们在一个多…...

最新版EasyRecovery数据恢复软件使用测评介绍

我们在逐渐适应信息电子化的同时&#xff0c;也有一些潜在的麻烦接踵而来&#xff0c;其中较为常见的就是文件和数据的保存问题。显然&#xff0c;设备的存储空间是有限的&#xff0c;这就不可避免地会出现数据被删除、覆盖或丢失的现象&#xff0c;如果丢失的是重要数据&#…...

关于知识图谱TransR

论文题目 Learning Entity and Relation Embeddings for Knowledge Graph Completion 论文链接 TransR 文中指出&#xff0c;不管是TransE还是TransH都是将实体和关系映射同一空间&#xff0c;但是&#xff0c;一个实体可能具有多个层面的信息&#xff0c;不同的关系可能关注…...

始于日志,不止于日志,Elastic Stack全面介绍

1、Elastic Stack是什么&#xff1f; 说Elastic Stack之前&#xff0c;先说一下ELK Stack。这个词相信很多人都是耳熟能详的&#xff0c;作为一个著名的日志系统解决方案&#xff0c;应用非常广泛。 “ELK”是三个开源项目的首字母缩写词&#xff1a;Elasticsearch、Logstash…...

FDX-B|EMID格式低频RFID 读卡模块LD6900技术选型与说明

FDX-B|EMID格式低频RFID 读卡模块LD6900是华翔天诚推出一款基于 RFID 无线射频识别技术的低频&#xff08;LF&#xff09;读卡模块&#xff0c;工作频率支持 134.2KHZ、125KHZ&#xff0c;符合 ISO 11784/5 国际标准&#xff0c;支持对 FDX-B、EMID 两种协议格式电子标签的读取…...

《SQL基础》11. 索引

SQL - 索引索引概述结构B-TreeBTreeHash思考分类语法SQL性能分析SQL执行频率慢查询日志profile详情explain执行计划索引失效情况范围查询索引列运算字符串不加引号模糊查询or连接条件数据分布影响使用规则最左前缀法则SQL提示覆盖索引前缀索引设计原则索引 概述 索引&#xf…...

【前端】进阶Mac OS软件商城页面_缤纷多彩的创意UI

非常漂亮的仿Mac OS界面&#xff0c;更改下参数就可以变成你需要的界面。 还可以一键更换背景主题 灵感来源于米科瓦伊加文齐奥夫斯基 附上css、html、js源码 下面是html文件 <!DOCTYPE html> <html lang"en" > <head><meta charset"…...

wordpress 自动跳转/网站seo外包

点击查看全文 讲师介绍 刘立兼 上海云贝网络科技有限公司首席架构师&#xff0c;数年来一直奋战在电商大数据领域。经历了一个又一个618/1111/1212。对面向大数据的高可用、高性能、易扩展的分布式架构技术有着深刻的理解&#xff0c;特别擅长基于云计算的系统架构。 直播…...

百度统计搜索词为什么有与网站不相关的词/工作手机

摘要&#xff1a;在当今信息化时代&#xff0c;大多数企业都需要网络支撑企业的ICT运行&#xff0c;提升企业运行效率&#xff0c;针对企业网络中的网元设备&#xff08;包括交换机&#xff0c;路由器&#xff0c;防火墙等&#xff09;&#xff0c;很多企业希望根据自身的业务特…...

网站建设中的技术问题/余姚网站如何进行优化

%{ 1.这就是传说中的多行注释 2.成功&#xff01; %} 注意是大括号哟...

工业产品设计工资/永州网站seo

案例&#xff1a;怎么看到电脑隐藏的文件&#xff1f; “有时候我在电脑找不到一些文件&#xff0c;听朋友说这些文夹可能是隐藏的&#xff0c;直接查找是找不到的。那怎么才能看到隐藏的文件呢&#xff1f;电脑怎么看隐藏的文件&#xff1f;有没有小伙伴知道具体的方法。” …...

潍坊网站建设官网/福建seo快速排名优化

今天做form表单提交遇到了两个问题: 1.提交后不能跳转到指定页面 jsp代码 <form class"form-horizontal" role"form"><p class"task-title">新增</p><div id"field-list"><!--表单项--></div><…...

关于国际贸易的网站/站长工具关键词查询

本题要求将输入的任意3个整数从小到大输出。 输入格式: 输入在一行中给出3个整数&#xff0c;其间以空格分隔。 输出格式: 在一行中将3个整数从小到大输出&#xff0c;其间以“->”相连。 输入样例: 4 2 8 输出样例: 2->4->8 #include<stdio.h> #include<…...