java nio 下载_基于零拷贝技术的的java NIO文件下载服务器

什么是零拷贝?

我们首先来认识一下传统的I/O操作。

假如说用户进程现在要把一个文件复制到另一个地方。

那么用户程序必须先把这个文件读入内存,然后再把内存里的数据写入另一个文件。

不过文件读入内存也不是直接读入用户进程的内存,而是先读入操作系统内核的内存,然后再从操作系统内核的内存区读到用户进程的内存。

与之对应的是,写文件也不是直接写到磁盘上的文件,而是用户进程先把自己内存的数据传到操作系统内核的内存,然后再从操作系统内核的内存区写到磁盘。而这其中涉及到诸多的系统调用。

因此看上去简单的操作至少要分为四部

1磁盘文件读入操作系统

2操作系统读到用户进程

3用户进程写到操作系统

4操作系统写入磁盘文件

零拷贝和传统I/O有和不同?

零拷贝就是指,传输一个文件的时候,不需要把文件读到用户进程再处理,而是直接把文件读到操作系统一个内存区,然后再移动到操作系统的另一个内存区,最后写入文件。

这样一来,步骤变成这样:

1磁盘文件读入操作系统

2操作系统把数据写入操作系统另一个区域

3操作系统写入磁盘文件

虽然只少了一步,但是这里不仅减少了数据移动的时间损耗,而且减少了系统调用的次数,因此大大缩短了时间。

更加详细的解释请看https://blog.csdn.net/u010530...

java里如何实现零拷贝呢?

这就要说起java nio中的FileChannel.transferTo()方法了,该方法是把FileChannel中的数据利用零靠的技术转移到另一个channel。这另一个channel往往是FileChannel,不过SocketChannel也是可以的:)。

简单实现(静态下载文件,不能根据用户指令来更改下载的文件。)

代码如下:

单线程版本:

package qiuqi.filedownloadtest;

import java.io.FileInputStream;

import java.io.IOException;

import java.net.InetSocketAddress;

import java.nio.channels.*;

import java.util.Iterator;

public class FileServer {

public static void main(String[] args) throws IOException {

startServer();

}

public static void startServer() throws IOException {

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

serverSocketChannel.bind(new InetSocketAddress(9999));

serverSocketChannel.configureBlocking(false);

Selector selector = Selector.open();

serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

while (selector.select() > 0)

{

Iterator iterator = selector.selectedKeys().iterator();

while (iterator.hasNext())

{

SelectionKey key = iterator.next();

iterator.remove();

if(key.isAcceptable())

{

SocketChannel socketChannel = serverSocketChannel.accept();

try (FileInputStream in = new FileInputStream("C:\\Users\\dell\\Desktop\\ZOL手机数据(1).rar")){

long size = in.available();

long num = 0;

long begin = 0;

while ( (num = in.getChannel().transferTo(begin,size,socketChannel))!=0)

{

size-=num;

begin += num;

}

socketChannel.close();

}

catch (IOException e){e.printStackTrace();}

}

}

}

}

}

多线程版本:

package qiuqi.filedownloadtest;

import java.io.FileInputStream;

import java.io.IOException;

import java.net.InetSocketAddress;

import java.nio.channels.*;

import java.util.Iterator;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class FileServer {

static ExecutorService threadpool = Executors.newCachedThreadPool();

public static void main(String[] args) throws IOException {

startServer();

}

public static void startServer() throws IOException {

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

serverSocketChannel.bind(new InetSocketAddress(9999));

serverSocketChannel.configureBlocking(false);

Selector selector = Selector.open();

serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

while (selector.select() > 0)

{

Iterator iterator = selector.selectedKeys().iterator();

while (iterator.hasNext())

{

SelectionKey key = iterator.next();

iterator.remove();

if(key.isAcceptable())

{

SocketChannel socketChannel = serverSocketChannel.accept();

threadpool.execute(new Runnable() {

@Override

public void run() {

try (FileInputStream in = new FileInputStream("C:\\Users\\dell\\Desktop\\ZOL手机数据(1).rar")){

long size = in.available();

long num = 0;

long begin = 0;

while ( (num = in.getChannel().transferTo(begin,size,socketChannel))!=0)

{

size-=num;

begin += num;

}

socketChannel.close();

}

catch (IOException e){e.printStackTrace();}

}

});

}

}

}

}

}

代码就不讲解了。如果学过java nio,那么理解上面的程序轻而易举。

如果不熟悉java nio的服务器编程那么请先学习再来观看。

最后我想说,java NIO真的是NEW IO即新的IO,而不是NonBlocking IO即非阻塞IO。因为在这套体系里,不仅仅提供了非阻塞的编程模型,而且提供了类似零拷贝,内存映射这样的新技术(对于操作系统来说早就有了)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值