Java NIO教程

1.简介

Java NIO是从Java 1.4引入的库。 自从Java NIO推出以来,它提供了另一种方法来处理I / O和网络事务。 它被认为是Java网络和Java IO库的替代方法。 开发Java NIO的目的是使输入和输出的事务异步和非阻塞。 阻塞和非阻塞IO的概念将在后面的部分中介绍。

目录

1.简介 2. IO中的术语
2.1阻止输入和输出 2.2无阻塞输入和输出
3. Java NIO术语
3.1缓冲区
3.1.1缓冲区属性 3.1.2读取和写入缓冲区 3.1.3标记并重置缓冲区
3.2频道
3.2.1通道分散和聚集 3.2.2频道转移
3.3选择器
4. NIO频道

4.1。 文件频道 4.2 SocketChannel 4.3 ServerSocketChannel
5.结论

2. Java NIO中的术语

Java NIO在使用Java的I / O处理中引入了许多新术语。 在较早的场景中,Java I / O基于字符流和字节流。 但是,使用Java NIO,现在可以通过通道读取和处理数据-通过Channel进入缓冲区或通过缓冲区进入通道。 在本节中,我们将讨论与Java NIO相关的各种术语,以帮助我们更好地理解进一步的教程。

2.1阻止输入和输出

使用字符流和字节流,文件被加载到JVM内存中并被锁定以进行读取或写入。 这导致其他试图读取同一文件的程序处于阻塞状态。 尽管有可用的处理能力,但由于程序被迫等待,因此这种情况浪费了CPU的能力。 读取或写入数据的这种安排称为阻塞输入和输出。

2.2无阻塞输入和输出

随着无阻塞输入和输出进入画面,数据开始被读取到通道中。 在无阻塞的输入和输出布置中,JVM使用通道来缓冲数据。 这些通道允许动态读取数据,而不会阻止文件供外部使用。 通道是一块缓冲的内存,一旦读取了先前的缓冲数据,就将其填充。 这样可以确保在完整的读取周期中不会阻止该文件,并且其他程序也可以对该文件进行必要的访问。

Java NIO主要涉及三个术语:

  • 频道
  • 选择器
  • 缓冲液

这些术语将在本文中进一步声明。

3. Java NIO –术语

如上所述,Java非阻塞IO在通道和缓冲区上工作。 在本节中,我们将尝试理解这些术语以及其他术语选择器。 这些术语对于遵循后续教程很重要。

3.1缓冲区

缓冲区是固定的一块内存,用于在将数据读入通道之前存储该数据。 缓冲区可确保预定义大小的数据,以加快文件,输入和数据流的读取速度。 缓冲区的大小可配置为2到幂n的块。

根据输入类型,可以使用各种类型的缓冲区:

  • ByteBuffer:用于按字节读取字符流或文件
  • CharBuffer:用于读取完整ASCII集内的字符
  • DoubleBuffer:专门用于双重数据值,例如来自传感器的读数
  • FloatBuffer:用于读取恒定数据流,用于分析之类的目的
  • LongBuffer:用于读取长数据类型的值
  • IntBuffer:用于读取分数或结果的整数值
  • ShortBuffer:用于读取短整数值

每个缓冲区都有其特定用途。 通常用于文件的缓冲区是ByteBufferCharBuffer。 创建字节缓冲区的简短示例如下所示。

RandomAccessFile aFile = new RandomAccessFile("src/data.txt", "rw");
FileChannel inChannel = aFile.getChannel();
ByteBuffer buf = ByteBuffer.allocate(48);

在上面的代码中,正在创建48个字节的缓冲区。 必须指定缓冲区大小。 第三行将48个字节的存储空间分配给缓冲区buf。 这样可以确保将必要的内存预先分配给缓冲区。 在继续使用它们进行通道读写之前,必须先了解缓冲区的读写过程。 下图显示了从文件读取字节的典型缓冲区。

Java NIO-缓冲区读取

缓冲区读取

可以看出,缓冲区读取并向左推送第一个字节。 缓冲区是后进先出类型的内存分配。 因此,当您希望使用缓冲区读取文件时,必须先将其翻转,然后才能读取文件。 没有翻转,数据将以相反的顺序输出。 为了翻转缓冲区,需要执行以下简单代码行:

buf.flip();

Java NIO-buffer.flip()

buffer.flip()

一旦将数据读入缓冲区,就该实际获取已读取的数据了。 为了读取数据,使用了buf.get()函数。 此函数调用在每次调用时都读取一个字节/字符/数据包,具体取决于缓冲区的类型。 读取可用数据后,还必须在下一次读取之前清理缓冲区。 必须进行清理以确保释放空间以读取更多数据。 为了清洗缓冲区,有两种可行的方法–清除缓冲区或压缩缓冲区。

要清除缓冲区,请执行命令buf.clear() 。 要压缩缓冲区,请使用命令buf.compact() 。 这两个命令最终都会做同样的事情。 但是, compact()仅清除使用函数buf.get()读取的数据。 因此,在需要继续优化缓冲区使用的内存量时使用它。

3.1.1缓冲区属性

缓冲区本质上具有3个属性:

  1. 缓冲位置
  2. 缓冲区限制
  3. 缓冲能力

在缓冲区写入期间,缓冲区位置是当前字节正在写入的位置。 在缓冲区读取过程中,缓冲区位置是从中读取字节的位置。 随着我们进行读取或写入操作,缓冲区位置不断动态变化。

在缓冲区写入期间,缓冲区限制是可以写入缓冲区的最大数据大小。 本质上,缓冲区限制和缓冲区容量在缓冲区写入期间是同义词。 但是,在缓冲区读取期间,缓冲区限制是可从缓冲区读取的可用字节数。 因此,当弹出字节时,缓冲区限制将继续减小。

缓冲区容量是可以在任何时间点写入缓冲区或从缓冲区读取的最大数据。 因此,上面分配的大小48也称为缓冲区容量。

3.1.2读取和写入缓冲区

缓冲区本质上是一种存储数据的介质,直到线程从缓冲区中读取数据并请求新数据为止。 从输入源读取数据的主要步骤是将数据读取到缓冲区中。 为了将数据读入缓冲区,使用了下面显示的代码段。

FileChannel inChannel = aFile.getChannel();
System.out.println("Created file Channel..");
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buf);

在上面的代码中,我们创建一个FileChannel从文件中读取数据,并创建一个缓冲区buf来保存数据。 然后,使用语句inChannel.read(buf)将缓冲区用于读取通道的数据。 执行此语句后,缓冲区现在将保留多达48个字节的可用数据。
为了开始读取数据,您使用了一个简单的语句buf.get()

3.1.3标记并重置缓冲区

在读取过程中,经常有一些情况需要重复从特定位置读取数据。 在正常情况下,一旦从缓冲区中获取数据,就认为该数据已消失。 但是,可以在特定的索引处标记缓冲区,从而可以再次从特定位置读取缓冲区。 下面的代码演示了如何完成此操作。

buffer.mark();char x = buffer.get();
char y = buffer.get();
char z = buffer.get();
char a = buffer.get();
//Do something with above databuffer.reset();  //set position back to mark.

标记和重置的主要应用是重复分析数据,重复重复信息,发送命令特定次数甚至更多。

3.2频道

通道是非阻塞IO的主要介质。 通道类似于可用于阻止IO的流。 这些通道支持网络数据以及文件数据IO。 当需要时,通道从缓冲区读取数据。 缓冲区保存数据,直到从缓冲区读取数据为止。

通道具有多种实现方式,具体取决于要读取的数据。 以下列出了可用于渠道的标准实现:

  • FileChannel:用于从文件读取数据和向文件写入数据
  • DatagramChannel:用于使用UDP数据包通过网络进行数据交换
  • SocketChannel:用于通过TCP套接字交换数据的TCP通道
  • ServerSocketChannel:类似于Web服务器的实现,它通过特定的TCP端口侦听请求。 它为每个新连接创建一个新的SocketChannel实例

从通道名称可以理解,除了文件IO之外,它们还涵盖UDP + TCP网络IO流量。 与可以在特定时刻读取或写入的Streams不同,同一Channel可以无缝读取和写入资源。 通道支持异步读写,这确保在不妨碍代码执行的情况下读取数据。 上面讨论的缓冲区支持通道的这种异步操作。

3.2.1通道分散和聚集

Java NIO固有地支持数据分散和收集,以便从多个缓冲区读取数据或将数据写入多个缓冲区。 Java NIO非常智能,可以管理多个缓冲区中的读取和写入。
Java NIO分散用于将通道中的读取分散到多个缓冲区中。 它的代码实现非常简单。 您需要做的就是添加一个缓冲区数组作为读取的参数。 下面显示了相同的代码段。

ByteBuffer buffer1 = ByteBuffer.allocate(128);
ByteBuffer buffer2   = ByteBuffer.allocate(128);
ByteBuffer[] buffers = {buffer1,buffer2};channel.read(buffers);

在上面的代码中,我们创建了两个每个128字节的缓冲区。 注意这里我们创建了一个包含两个缓冲区的数组。 该数组进一步作为参数传递给读取的通道。 通道将数据读入第一个缓冲区,直到达到缓冲区容量。 一旦达到缓冲区容量,通道将自动切换到下一个缓冲区。 因此,读取的通道被分散而对线程没有任何影响。
Java NIO收集也以类似的方式工作。 读取到多个缓冲区的数据也可以收集并写入单个通道。 下面的代码片段做了类似的事情。

ByteBuffer buffer1 = ByteBuffer.allocate(128);
ByteBuffer buffer2   = ByteBuffer.allocate(128);
ByteBuffer[] buffers = {buffer1,buffer2};channel.write(buffers);

该代码类似于分散读取。 需要理解的是信息的写入顺序。 该信息从第一个缓冲区开始写入通道。 达到第一个缓冲区的限制后,通道会自动切换到下一个缓冲区。 重要的是要注意在此写入过程中不会发生翻转。 如果需要在写入之前翻转缓冲区,则需要在将缓冲区分配给数组之前完成。

3.2.2频道转移

顾名思义,通道传输是将数据从一个通道传输到另一个通道的过程。 可以从通道缓冲区的特定位置进行通道传输。 但是,在位置值设置为零的情况下,可以将完整的输入源复制或复制到指定的输出目标。 例如,在关键字和文本编辑器之间建立通道,将使您能够将输入从键盘连续传输到文本编辑器。
为了促进通道传输,Java NIO配备了两个函数,即transferFrom()transferTo() 。 这些功能的用途从它们的标识符中很清楚。 让我们以一个例子来更好地理解这些功能。
我们将使用上面创建的data.txt文件作为输入源。 我们会将数据从该文件传输到新文件output.txt 。 下面的代码使用transferFrom()方法调用执行相同的操作。

ChannelTransfer.java

import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;public class ChannelTransfer {public static void main(String[] args) {try {RandomAccessFile copyFrom = new RandomAccessFile("src/data.txt", "rw");FileChannel fromChannel = copyFrom.getChannel();RandomAccessFile copyTo = new RandomAccessFile("src/output.txt", "rw");FileChannel toChannel = copyTo.getChannel();long count = fromChannel.size();toChannel.transferFrom(fromChannel, 0, count);} catch (Exception e) {System.out.println("Error: " + e);}}
}

从上面的代码中可以看出,通道fromChannel用于从data.txt中读取数据。 toChannel用于从位置0开始的fromChannel获取数据。重要的是要注意,整个文件都是使用FileChannel复制的。 但是,在SocketChannel某些实现中,情况可能并非如此。 在这种情况下,仅复制在传输时可在缓冲区中读取的数据。 此行为归因于SocketChannel实现的动态性质。

transferTo的实现非常相似。 唯一需要做的更改是方法调用将使用源对象完成,而目标通道对象将是方法调用中的一个参数。

3.3选择器

顾名思义,选择器用于从多个通道中选择一个通道。 当您计划使用单个线程并行管理多个资源时,Java NIO中的选择器特别有用。 选择器充当线程和开放通道之间的桥梁。 选择器通常在预期线程流量较低但需要使用多个资源的情况下使用。 下面描述了角色选择器可能扮演的角色的示意图。

Java NIO-NIO选择器

NIO选择器

选择器的创建非常简单。 下面的代码段说明了如何创建选择器以及如何在选择器中注册频道。

Selector myFirstSelector = Selector.open(); //opens the selector
SocketChannel channel = SocketChannel.open();
channel.configureBlocking(false);
SelectionKey selectorKey = channel.register(myFirstSelector, SelectionKey.OP_READ);

上面的代码创建一个SocketChannel ,将其配置为非阻塞并将其注册到选择器。 请注意,我们使用了SocketChannel 。 选择器需要一个可以配置为非阻塞的通道。 因此,选择器不能与FileChannel一起使用。
需要注意的另一点是注册SocketChannel的第二个参数。 参数指定我们要监视的通道事件。 选择器等待事件并在触发事件时更改其状态。 这些事件在下面列出:

  1. 连接
  2. 接受

可以使用如下所示的静态常量来配置这些事件:

  1. SelectionKey.OP_CONNECT
  2. SelectionKey.OP_ACCEPT
  3. SelectionKey.OP_READ
  4. SelectionKey.OP_WRITE

选择器为我们提供了预定义的功能,以检查这些事件的发生。 下面的方法调用是不言自明的,可用于监视这些事件的发生。

key.isAcceptable();
key.isConnectable();
key.isReadable();
key.isWritable();

因此,当我们计划用较少的线程管理多个资源时,选择器非常有用。

4. NIO频道

4.1文件通道

这种类型的通道通常用于读取和写入文件。 下面显示了用于创建通道并将其用于读写的示例代码

ChannelRW.java

import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;public class ChannelRW {public static void main(String[] args) {System.out.println("Starting the file read..");try {RandomAccessFile aFile = new RandomAccessFile("src/data.txt", "rw");FileChannel inChannel = aFile.getChannel();System.out.println("Created file Channel..");ByteBuffer buf = ByteBuffer.allocate(48);int bytesRead = inChannel.read(buf);while (bytesRead != -1) {System.out.println("\nRead " + bytesRead);buf.flip();while(buf.hasRemaining()){System.out.print((char) buf.get());}buf.clear();bytesRead = inChannel.read(buf);}aFile.close();}catch(Exception e) {System.out.println("Error:"+e);}}
}

data.txt

Hello,
This is my first NIO read. I am reading multiple lines.
The code is implemented for Javacodegeeks by Abhishek Kothari

在上面的代码中,我们试图读取如上所示创建的data.txt文件。 正在使用Java NIO库读取该文件。 文件读取过程涉及多个步骤。 下面显示了针对它的逐步代码说明。

  1. 使用RandomAccessFile对象打开文件。 这样可以确保文件不会被阻止访问。 类名建议,仅在需要时才允许随机访问文件。 因此,IO本质上是非阻塞的
  2. 从上面创建的对象中获取FileChannel对象。 该通道有助于根据需要从文件中读取数据。 通道是文件和缓冲区之间的一种隧道设置
  3. 创建一个缓冲区来存储从通道读取的字节。 注意,我们已经指定了缓冲区大小。 因此,将始终以48个字节的块读取数据。
  4. 从缓冲区读取数据,直到读取的字节数变为负数为止。
  5. 翻转缓冲区后,打印已读取的数据。 上面已经解释了缓冲器翻转的原因。
  6. 关闭文件对象以防止任何形式的内存泄漏

上面代码的输出如下所示:

Starting the file read..
Created file Channel..Read 48
Hello,
This is my first NIO read. I am reading m
Read 48
ultiple lines.
The code is implemented for Javac
Read 28
odegeeks by Abhishek Kothari

可见,数据以48个字节的块读取,并且每次出现“ Read 48 ”语句以显示已读取的字节数。 可以看出,当到达文件末尾时,只能读取28个字节,因此返回计数28。

4.2 SocketChannel

这种类型的通道用于连接到http套接字。 连接到套接字的简单代码如下所示:

SocketChannel sc = SocketChannel.open();
sc.connect(new InetSocketAddress("https://javacodegeeks.com", 8080));

套接字通道在执行方法调用时连接到指定的URL。 为了关闭打开的通道,只需执行如下所示的相应方法调用即可。

sc.close();

SocketChannel读取数据的过程类似于FileChannel

4.3 ServerSocketChannel

服务器套接字通道用于读取来自套接字客户端的套接字数据。 可以使用以下代码段将该通道配置为读取。

ServerSocketChannel ssc = ServerSocketChannel.open();ssc.socket().bind(new InetSocketAddress(8080));while(true){SocketChannel sc =ssc.accept();//do something with sc...
}

上面的代码打开服务器端套接字,并允许来自外部SocketChannel客户端的套接字连接。 从上面的代码可以理解, ServerSocketChannel仅需要端口号即可启动套接字服务器。 一旦启动,它可以创建自己的SocketChannel来接受来自其他套接字的数据。 这就是使用Java NIO进行无阻塞Socket IO连接的方式。

5.结论

本文详细讨论了Java NIO的各种术语。 它说明了使用各种NIO通道以非阻塞方式读取和写入数据的过程。 关于Java NIO库(如DatagramChannel,Pipes,Async通道等),还有更多需要探索的地方。

翻译自: https://www.javacodegeeks.com/2018/07/java-nio-tutorial.html

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

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

相关文章

关于判断函数凸或凹以及最优化的问题

大部分情况下都转换为凸优化问题&#xff0c;并通过最优化方法来求解&#xff0c;因此了解相关知识就显得尤为重要了。 主要内容&#xff1a; 问题引出凸集凸函数凸优化最优化 1、问题引出 在n维空间中&#xff0c;对于任意两个点&#xff0c;对于0<μ<1&#xff0c;…

javafx弹出式窗口_JavaFX 8的弹出式编辑器

javafx弹出式窗口在过去的几个月中&#xff0c;我很高兴与JavaFX 8一起使用&#xff0c;以便为计划和调度应用程序实现复杂的用户界面。 所需的功能之一是执行“就地”编辑的方法&#xff0c;即快速编辑用户选择对象的某些基本属性的方法。 遵循“如果您无法创新&#xff0c;就…

随机访问MAC协议 知识梳理(ALOHA,CSMA,CSMA/CD,CSMA/CA)

0、随机访问MAC的协议 数据链路层动态随机分配信道时对随机访问MAC协议&#xff1a;ALOHA&#xff0c;CSMA&#xff0c;CSMA/CD&#xff0c;CSMA/CA ALOHA&#xff0c;CSMA&#xff0c;CSMA/CD的区别仅在于是否对信道进行监听和是否有碰撞检测&#xff1a; 1、ALOHA&#xf…

认识CUBA平台的CLI

毫无疑问&#xff0c;软件开发人员&#xff08;尤其是Java开发人员&#xff09;的世界充满了键盘狂热者&#xff0c;最好是一次单击即可键入10-15个字母。 而且我们的社区也不例外&#xff0c;因此经常有人问我们“如何在没有CUBA Studio的情况下启动项目&#xff1f;”之类的问…

将matlab中数据输出保存为txt或dat格式

一、将matlab中数据输出保存为txt或dat格式的三种方法。 第一种方法&#xff1a;save&#xff08;最简单基本的&#xff09; 具体的命令是&#xff1a;用save *.txt -ascii x x为变量 *.txt为文件名,该文件存储于当前工作目录下&#xff0c;再打开就可以打开后,数据有可能是以…

马尔可夫链笔记

1 引言 之前学习了伯努利过程和泊松过程&#xff0c;它们是无记忆性&#xff0c;不依赖于过去的状态&#xff0c;今天学习了马尔可夫链&#xff0c;它会依赖于过去的过程&#xff0c;更准确的说是依赖于过去的某种状态。 2 离散时间的马尔可夫链&#xff08;Markov Chain, MC…

「协方差」与「相关系数」的概念

一、协方差&#xff1a; 可以通俗的理解为&#xff1a;两个变量在变化过程中是同方向变化&#xff1f;还是反方向变化&#xff1f;同向或反向程度如何&#xff1f; 你变大&#xff0c;同时我也变大&#xff0c;说明两个变量是同向变化的&#xff0c;这时协方差就是正的。 你…

垃圾收集 java_关于Java垃圾收集

垃圾收集 java本文讨论的是使用的最流行的框架之一带来的开销–我敢打赌&#xff0c;几乎没有应用程序不使用java.util.Collections。 本文基于以下事实&#xff1a;框架为例如集合的初始大小提供了默认值。 因此&#xff0c;我们有一个假设&#xff0c;即大多数人不会费心地自…

Latex \bibliographystyle+修改字体字号的大小

1. bibliography style LaTeX 标准选项及其样式共有以下8种&#xff1a; plain &#xff0c;按字母的顺序排列&#xff0c;比较次序为作者、年度和标题. unsrt &#xff0c;样式同plain&#xff0c;只是按照引用的先后排序. alpha &#xff0c;用作者名首字母年份后两位作标号…

boxplot

1. 简介 箱形图&#xff0c;又称为盒须图、盒式图、盒状图或箱线图&#xff0c;是一种用作显示一组数据分散情况资料的统计图。箱形图于1977年由美国著名统计学家约翰图基&#xff08;John Tukey&#xff09;发明。它能显示出一组数据的最大值、最小值、中位数、上下四分位数及…

Java 11的期望

过去的几年对Java世界一直是动荡不安的&#xff0c;在相当多的发行版中添加了各种各样的功能。 在开发人员社区中&#xff0c;人们逐渐意识到Java的开发速度不够快。 在最初的20年中&#xff0c;Java平台和Java开发工具包&#xff08;JDK&#xff09;经历了庞大&#xff0c;不…

martingale与Markov Process的关系

鞅过程与马尔科夫过程是什么关系&#xff1f; 1.鞅代表的是公平游戏&#xff0c;马尔可夫过程侧重过程无记忆性 总而言之&#xff1a;鞅和马尔可夫过程没有包含的关系。因为鞅代表的是公平游戏&#xff0c;而马尔可夫过程侧重过程无记忆性。两者没有内在联系。 注&#xff1…

LaTeX双栏模板插入通栏公式(跨栏插图)

1. 利用带星号的浮动体环境 带星号的浮动体figure和table环境可以在双栏模板中使用&#xff0c;例如我们以IEEEtran为例&#xff0c;插入通栏公式 \documentclass{IEEEtran} \usepackage{amsmath&#xff0c;lipsum} \begin{document} \lipsum[1] \begin{figure*} \begin{ali…

renew process 更新过程

一个泊松过程可以分解成一系列 i.i.di.i.di.i.d 的指数分布随机变量相加&#xff0c;如果把指数分布换成其他 i.i.di.i.di.i.d 的分布就得到了更新过程。 更新过程本身是泊松过程的一种扩长&#xff0c;同时更新过程也可以发展出一套更新理论&#xff0c;包括更新方程等。 htt…

离散时间信号,连续时间信号,模拟信号,数字信号区别

连续时间信号 &#xff1a; 在时间t 上是连续的值 时间连续&#xff0c; 幅值连续。 定义为模拟信号。时间连续&#xff0c; 幅值离散。 比如脉冲信号。 离散时间信号 &#xff1a; 在时间t上 是离散的值 时间离散&#xff0c; 幅值连续。 &#xff08;在任意两个离散时间点…

java8 javafx_Java8中的外观(JavaFX8)

java8 javafxJavaFX8在外观方面进行了一些更改 &#xff0c;其中最相关的是新CSS API &#xff0c;它允许您为控件以及已公开的Skin类创建新CSS属性和伪类。 使用CSS可以更改控件的很多外观&#xff0c;但是CSS可以实现很多功能&#xff0c;这就是Skin类的用处。从“ UI控件体…

如何通俗易懂地解释卷积?

马同学 从数学上讲&#xff0c;卷积就是一种运算。 某种运算&#xff0c;能被定义出来&#xff0c;至少有以下特征&#xff1a; 首先是抽象的、符号化的 其次&#xff0c;在生活、科研中&#xff0c;有着广泛的作用 比如加法&#xff1a; [公式] &#xff0c;是抽象的&…

具有中央异常处理和VO验证的Spring Data JPA –框架

1.简介 一段时间以来&#xff0c;Spring框架已成为事实上的标准&#xff0c;可以创建任何基于REST API的应用程序。 Spring提供了各种现成的组件&#xff0c;以避免编写重复而繁琐的样板代码。 另外&#xff0c;关于Spring的美丽之处在于&#xff0c;如果有现成的解决方案&…

初识斯蒂尔杰斯积分(Stieltjes integral)

https://blog.csdn.net/Northernland/article/details/83051415

drools6.5_使用Drools 6.0进行部署

drools6.5KieScanner 6.0 KieScanner取代了5.x KnowledgeAgent。 它使用嵌入式Maven允许在运行时解析和检索jar。 6.0应用程序现在可以轻松支持依赖关系和可传递依赖关系&#xff1b; 使用众所周知的Maven语义进行版本控制。 它允许在类路径上部署&#xff0c;也可以在运行时动…