本文目录一览:
- 1、Java中nio与普通io有什么优势?
- 2、Java NIO和IO的区别
- 3、介绍一下Java NIO,NIO读取文件都有哪些方法
- 4、Java中IO与NIO的区别和使用场景
- 5、Java NIO与IO的区别和比较
Java中nio与普通io有什么优势?
1,nio的主要作用就是用来解决速度差异的。举个例子:计算机处理的速度,和用户按键盘的速度,这两者的速度相差悬殊。
2,如果按照经典的方法:一个用户设定一个线程,专门等待用户的输入,无形中就造成了严重的资源浪费,每一个线程都需要珍贵的cpu时间片,由于速度差异造成了在这个交互线程中的cpu都用来等待。
3,传统的阻塞式IO,每个连接必须要开一个线程来处理,并且没处理完线程不能退出。
4,非阻塞式IO,由于基于反应器模式,用于事件多路分离和分派的体系结构模式,所以可以利用线程池来处理。事件来了就处理,处理完了就把线程归还。
5,而传统阻塞方式不能使用线程池来处理,假设当前有10000个连接,非阻塞方式可能用1000个线程的线程池就搞定了,而传统阻塞方式就需要开10000个来处理。如果连接数较多将会出现资源不足的情况。非阻塞的核心优势就在这里。-javanio
Java NIO和IO的区别
Java
NIO和IO的主要区别如下:
1.NIO
的创建目的是为了让
Java
程序员可以实现高速
I/O
而无需编写自定义的本机代码。NIO
将最耗时的
I/O
操作(即填充和提取缓冲区)转移回操作系统,因而可以极大地提高速度。传统的IO操作属于阻塞型,严重影响程序的运行速度。
2,。流与块的比较。原来的
I/O
库(在
java.io.*中)
与
NIO
最重要的区别是数据打包和传输的方式。正如前面提到的,原来的
I/O
以流的方式处理数据,而
NIO
以块的方式处理数据。
面向流
的
I/O
系统一次一个字节地处理数据。一个输入流产生一个字节的数据,一个输出流消费一个字节的数据。为流式数据创建过滤器非常容易。链接几个过滤器,以便每个过滤器只负责单个复杂处理机制的一部分,这样也是相对简单的。不利的一面是,面向流的-javanio
I/O
通常相当慢。
3.一个
面向块
的
I/O
系统以块的形式处理数据。每一个操作都在一步中产生或者消费一个数据块。按块处理数据比按(流式的)字节处理数据要快得多。但是面向块的
I/O
缺少一些面向流的
I/O
所具有的优雅性和简单性。
介绍一下Java NIO,NIO读取文件都有哪些方法
NIO也就是New I/O,是一组扩展Java IO操作的API集, 于Java 1.4起被引入,Java 7中NIO又提供了一些新的文件系统API,叫NIO2.
NIO2提供两种主要的文件读取方法:
使用buffer和channel类
使用Path 和 File 类
NIO读取文件有以下三种方式:
1. 旧的NIO方式,使用BufferedReader
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class WithoutNIOExample
{
public static void main(String[] args)
{
BufferedReader br = null;
String sCurrentLine = null;
try
{
br = new BufferedReader(
new FileReader("test.txt"));
while ((sCurrentLine = br.readLine()) != null)
{
System.out.println(sCurrentLine);
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
if (br != null)
br.close();
} catch (IOException ex)
{
ex.printStackTrace();
}
}
}
}
2. 使用buffer读取小文件
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class ReadFileWithFileSizeBuffer
{
public static void main(String args[])
{
try
{
RandomAccessFile aFile = new RandomAccessFile(
"test.txt","r");
FileChannel inChannel = aFile.getChannel();
long fileSize = inChannel.size();
ByteBuffer buffer = ByteBuffer.allocate((int) fileSize);
inChannel.read(buffer);
buffer.rewind();
buffer.flip();
for (int i = 0; i fileSize; i++)
{
System.out.print((char) buffer.get());
}
inChannel.close();
aFile.close();
}
catch (IOException exc)
{
System.out.println(exc);
System.exit(1);
}
}
}
3. 分块读取大文件
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class ReadFileWithFixedSizeBuffer
{
public static void main(String[] args) throws IOException
{
RandomAccessFile aFile = new RandomAccessFile
("test.txt", "r");
FileChannel inChannel = aFile.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
while(inChannel.read(buffer) 0)
{
buffer.flip();
for (int i = 0; i buffer.limit(); i++)
{
System.out.print((char) buffer.get());
}
buffer.clear(); // do something with the data and clear/compact it.
}
inChannel.close();
aFile.close();
}
}
4. 使用MappedByteBuffer读取文件
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
public class ReadFileWithMappedByteBuffer
{
public static void main(String[] args) throws IOException
{
RandomAccessFile aFile = new RandomAccessFile
("test.txt", "r");
FileChannel inChannel = aFile.getChannel();
MappedByteBuffer buffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
buffer.load();?
for (int i = 0; i buffer.limit(); i++)
{
System.out.print((char) buffer.get());
}
buffer.clear(); // do something with the data and clear/compact it.
inChannel.close();
aFile.close();
}
}
Java中IO与NIO的区别和使用场景
在java2以前,传统的socket IO中,需要为每个连接创建一个线程,当并发的连接数量非常巨大时,线程所占用的栈内存和CPU线程切换的开销将非常巨大。java5以后使用NIO,不再需要为每个线程创建单独的线程,可以用一个含有限数量线程的线程池,甚至一个线程来为任意数量的连接服务。由于线程数量小于连接数量,所以每个线程进行IO操作时就不能阻塞,如果阻塞的话,有些连接就得不到处理,NIO提供了这种非阻塞的能力。-javanio
NIO 设计背后的基石:反应器模式,用于事件多路分离和分派的体系结构模式。
反应器(Reactor):用于事件多路分离和分派的体系结构模式
通常的,对一个文件描述符指定的文件或设备, 有两种工作方式: 阻塞 与非阻塞 。所谓阻塞方式的意思是指, 当试图对该文件描述符进行读写时, 如果当时没有东西可读,或者暂时不可写, 程序就进入等待 状态, 直到有东西可读或者可写为止。而对于非阻塞状态, 如果没有东西可读, 或者不可写, 读写函数马上返回, 而不会等待 。-javanio
一种常用做法是:每建立一个Socket连接时,同时创建一个新线程对该Socket进行单独通信(采用阻塞的方式通信)。这种方式具有很高的响应速度,并且控制起来也很简单,在连接数较少的时候非常有效,但是如果对每一个连接都产生一个线程的无疑是对系统资源的一种浪费,如果连接数较多将会出现资源不足的情况。-javanio
另一种较高效的做法是:服务器端保存一个Socket连接列表,然后对这个列表进行轮询,如果发现某个Socket端口上有数据可读时(读就绪),则调用该socket连接的相应读操作;如果发现某个 Socket端口上有数据可写时(写就绪),则调用该socket连接的相应写操作;如果某个端口的Socket连接已经中断,则调用相应的析构方法关闭该端口。这样能充分利用服务器资源,效率得到了很大提高。-javanio
传统的阻塞式IO,每个连接必须要开一个线程来处理,并且没处理完线程不能退出。
非阻塞式IO,由于基于反应器模式,用于事件多路分离和分派的体系结构模式,所以可以利用线程池来处理。事件来了就处理,处理完了就把线程归还。而传统阻塞方式不能使用线程池来处理,假设当前有10000个连接,非阻塞方式可能用1000个线程的线程池就搞定了,而传统阻塞方式就需要开10000个来处理。如果连接数较多将会出现资源不足的情况。非阻塞的核心优势就在这里。-javanio
为什么会这样,下面就对他们做进一步细致具体的分析:
首先,我们来分析传统阻塞式IO的瓶颈在哪里。在连接数不多的情况下,传统IO编写容易方便使用。但是随着连接数的增多,问题传统IO就不行了。因为前面说过,传统IO处理每个连接都要消耗一个线程,而程序的效率当线程数不多时是随着线程数的增加而增加,但是到一定的数量之后,是随着线程数的增加而减少。这里我们得出结论,传统阻塞式IO的瓶颈在于不能处理过多的连接。-javanio
然后,非阻塞式IO的出现的目的就是为了解决这个瓶颈。而非阻塞式IO是怎么实现的呢?非阻塞IO处理连接的线程数和连接数没有联系,也就是说处理 10000个连接非阻塞IO不需要10000个线程,你可以用1000个也可以用2000个线程来处理。因为非阻塞IO处理连接是异步的。当某个链接发送请求到服务器,服务器把这个连接请求当作一个请求"事件",并把这个"事件"分配给相应的函数处理。我们可以把这个处理函数放到线程中去执行,执行完就把线程归还。这样一个线程就可以异步的处理多个事件。而阻塞式IO的线程的大部分时间都浪费在等待请求上了。-javanio
所谓阻塞式IO流,就是指在从数据流当中读写数据的的时候,阻塞当前线程,直到IO流可以
重新使用为止,你也可以使用流的avaliableBytes()函数看看当前流当中有多少字节可以读取,这样
就不会再阻塞了。
Java NIO与IO的区别和比较
传统的socket IO中,需要为每个连接创建一个线程,当并发的连接数量非常巨大时,线程所占用的栈内存和CPU线程切换的开销将非常巨大。使用NIO,不再需要为每个线程创建单独的线程,可以用一个含有限数量线程的线程池,甚至一个线程来为任意数量的连接服务。由于线程数量小于连接数量,所以每个线程进行IO操作时就不能阻塞,如果阻塞的话,有些连接就得不到处理,NIO提供了这种非阻塞的能力。-javanio
小量的线程如何同时为大量连接服务呢,答案就是就绪选择。这就好比到餐厅吃饭,每来一桌客人,都有一个服务员专门为你服务,从你到餐厅到结帐走人,这样方式的好处是服务质量好,一对一的服务,VIP啊,可是缺点也很明显,成本高,如果餐厅生意好,同时来100桌客人,就需要100个服务员,那老板发工资的时候得心痛死了,这就是传统的一个连接一个线程的方式。-javanio
老板是什么人啊,精着呢。这老板就得捉摸怎么能用10个服务员同时为100桌客人服务呢,老板就发现,服务员在为客人服务的过程中并不是一直都忙着,客人点完菜,上完菜,吃着的这段时间,服务员就闲下来了,可是这个服务员还是被这桌客人占用着,不能为别的客人服务,用华为领导的话说,就是工作不饱满。那怎么把这段闲着的时间利用起来呢。这餐厅老板就想了一个办法,让一个服务员(前台)专门负责收集客人的需求,登记下来,比如有客人进来了、客人点菜了,客人要结帐了,都先记录下来按顺序排好。每个服务员到这里领一个需求,比如点菜,就拿着菜单帮客人点菜去了。点好菜以后,服务员马上回来,领取下一个需求,继续为别人客人服务去了。这种方式服务质量就不如一对一的服务了,当客人数据很多的时候可能需要等待。但好处也很明显,由于在客人正吃饭着的时候服务员不用闲着了,服务员这个时间内可以为其他客人服务了,原来10个服务员最多同时为10桌客人服务,现在可能为50桌,60客人服务了。-javanio
这种服务方式跟传统的区别有两个:
1、增加了一个角色,要有一个专门负责收集客人需求的人。NIO里对应的就是Selector。
2、由阻塞服务方式改为非阻塞服务了,客人吃着的时候服务员不用一直侯在客人旁边了。传统的IO操作,比如read(),当没有数据可读的时候,线程一直阻塞被占用,直到数据到来。NIO中没有数据可读时,read()会立即返回0,线程不会阻塞。-javanio
NIO中,客户端创建一个连接后,先要将连接注册到Selector,相当于客人进入餐厅后,告诉前台你要用餐,前台会告诉你你的桌号是几号,然后你就可能到那张桌子坐下了,SelectionKey就是桌号。当某一桌需要服务时,前台就记录哪一桌需要什么服务,比如1号桌要点菜,2号桌要结帐,服务员从前台取一条记录,根据记录提供服务,完了再来取下一条。这样服务的时间就被最有效的利用起来了。-javanio