`
liuxinglanyue
  • 浏览: 565291 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

java学习——NIO篇2

阅读更多

在前面写的nio学习中是采取的简单的demo,后来在网上看到一个demo,一个用来多线程下载的demo,在这个demo里才会体现nio的高性能之处。充分体现nio的优势。

场景:一个服务端,然后100个客户端同时连接服务端,然后下载一个文件下来。服务端只需要一个连接来处理这些来自客户端的连接。其中对文件的传递采用的是nio中的FileChannel 。很好用的一个东西。

 

忘记从哪里转过来的代码了。。。

 


服务端:

import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Iterator;

public class NIOServer {
    static int BLOCK = 4096;

    // 处理与客户端的交互
    public class HandleClient {
        protected FileChannel channel;
        protected ByteBuffer buffer;

        public HandleClient() throws IOException {
            this.channel = new FileInputStream(filename).getChannel();
            this.buffer = ByteBuffer.allocate(BLOCK);
        }

        public ByteBuffer readBlock() {
            try {
                buffer.clear();
                int count = channel.read(buffer);
                buffer.flip();
                if (count <= 0)
                    return null;
            } catch (IOException e) {
                e.printStackTrace();
            }
            return buffer;
        }

        public void close() {
            try {
                channel.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    protected Selector selector;
    protected String filename = "d:\\test.jpg"; // a big file
    protected ByteBuffer clientBuffer = ByteBuffer.allocate(BLOCK);
    protected CharsetDecoder decoder;

    public NIOServer(int port) throws IOException {
        selector = this.getSelector(port);
        Charset charset = Charset.forName("GB2312");
        decoder = charset.newDecoder();
    }

    // 获取Selector
    protected Selector getSelector(int port) throws IOException {
        ServerSocketChannel server = ServerSocketChannel.open();
        Selector sel = Selector.open();
        server.socket().bind(new InetSocketAddress(port));
        server.configureBlocking(false);
        server.register(sel, SelectionKey.OP_ACCEPT);
        return sel;
    }

    // 监听端口
    public void listen() {
        try {
            for (;;) {
                selector.select();
                Iterator iter = selector.selectedKeys().iterator();
                while (iter.hasNext()) {
                    SelectionKey key = (SelectionKey) iter.next();
                    iter.remove();
                    handleKey(key);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 处理事件
    protected void handleKey(SelectionKey key) throws IOException {
        if (key.isAcceptable()) { // 接收请求
            ServerSocketChannel server = (ServerSocketChannel) key.channel();
            SocketChannel channel = server.accept();
            channel.configureBlocking(false);
            channel.register(selector, SelectionKey.OP_READ);
        } else if (key.isReadable()) { // 读信息
            System.out.println("能读");
            SocketChannel channel = (SocketChannel) key.channel();
            int count = channel.read(clientBuffer);
            if (count > 0) {
                clientBuffer.flip();
                CharBuffer charBuffer = decoder.decode(clientBuffer);
                System.out.println("Client >>" + charBuffer.toString());
                SelectionKey wKey = channel.register(selector, SelectionKey.OP_WRITE);
                wKey.attach(new HandleClient());
            } else
                channel.close();
            clientBuffer.clear();
        } else if (key.isWritable()) { // 写事件
            System.out.println("能写");
            SocketChannel channel = (SocketChannel) key.channel();
            HandleClient handle = (HandleClient) key.attachment();
            ByteBuffer block = handle.readBlock();
            if (block != null)
                channel.write(block);
            else {
                handle.close();
                channel.close();
            }
        }
    }

    public static void main(String[] args) {
        int port = 12345;
        try {
            NIOServer server = new NIOServer(port);
            System.out.println("Listernint on " + port);
            while (true) {
                server.listen();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

 客户端:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class NIOClient {
    static int SIZE = 10;
    static InetSocketAddress ip = new InetSocketAddress("localhost", 12345);
    static CharsetEncoder encoder = Charset.forName("GB2312").newEncoder();
    static FileChannel[] filechannel = new FileChannel[SIZE];

    static class Download implements Runnable {
        protected int index;

        public Download(int index) {
            this.index = index;
        }

        public void run() {
            try {
                long start = System.currentTimeMillis();
                SocketChannel client = SocketChannel.open();
                client.configureBlocking(false);
                Selector selector = Selector.open();
                client.register(selector, SelectionKey.OP_CONNECT);
                client.connect(ip);
                ByteBuffer buffer = ByteBuffer.allocate(8 * 1024);
                int total = 0;
                boolean flag = true;
                while (flag) {
                    selector.select();
                    Iterator iter = selector.selectedKeys().iterator();
                    while (iter.hasNext()) {
                        SelectionKey key = iter.next();
                        iter.remove();
                        if (key.isConnectable()) {
                            SocketChannel channel = (SocketChannel) key.channel();
                            if (channel.isConnectionPending())
                                channel.finishConnect();
                            channel.write(encoder.encode(CharBuffer.wrap("Hello from " + index)));
                            channel.register(selector, SelectionKey.OP_READ);
                        } else if (key.isReadable()) {
                            SocketChannel channel = (SocketChannel) key.channel();
                            int count = channel.read(buffer);
                            if (count > 0) {
                                writeToFile(buffer, index);
                                total += count;
                                buffer.clear();
                            } else {
                                filechannel[index].close();
                                client.close();
                                flag = false;
                            }
                        }
                    }
                }
                double last = (System.currentTimeMillis() - start) * 1.0 / 1000;
                System.out.println("Thread " + index + " downloaded " + total + "bytes in " + last + "s.");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static synchronized void writeToFile(ByteBuffer bb, int index) {
        try {
            if (filechannel[index] == null) {
                filechannel[index] = new FileOutputStream(new File("test" + index + ".jpg")).getChannel();
            }
            bb.flip();
            filechannel[index].write(bb);

        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {
        ExecutorService exec = Executors.newFixedThreadPool(SIZE);
        for (int index = 0; index < SIZE; index++) {
            exec.execute(new Download(index));
        }
        exec.shutdown();
    }
}
 
分享到:
评论

相关推荐

    Java NIO——Java NIO

    Java NIO——Java NIO——Java NIO

    大数据学习之旅——NIO源码

    本篇文章将带你深入理解NIO的源码,揭示其在大数据环境下的应用与优势。 NIO与传统的IO模型(-blocking I/O)相比,主要的区别在于它允许单线程处理多个通道(channels),而无需为每个通道创建一个单独的线程。...

    Java NIO——Selector机制解析三(源码分析)

    Java NIO,全称为Non-blocking Input/Output,是Java在1.4版本引入的一个新特性,旨在提供一种更高效、更灵活的I/O操作方式。相比于传统的BIO(Blocking I/O),NIO允许我们以非阻塞的方式读写数据,提高了系统资源...

    Java NIO学习笔记——ByteBuffer用法

    ByteBuffer的用法是Java NIO学习中的核心内容。 首先,我们了解下ByteBuffer的基本概念。ByteBuffer是一个字节缓冲区,可以存储字节序列。在NIO中,所有的数据读写都通过缓冲区进行,ByteBuffer与其他类型的Buffer...

    Java语言基础教程-Java NIO流篇2

    首先,我们要理解Java NIO的核心组件之一——流。在Java的IO体系中,流是数据传输的抽象,它代表了数据的流向,可以是输入流(InputStream)或输出流(OutputStream)。然而,NIO中的流与传统的IO流有所不同,它们...

    java基础——————试题库

    这份“java基础——————试题库”资源旨在帮助学习者系统地复习和深入理解Java的基础知识,确保他们能够全方位地掌握这一强大的编程工具。下面将详细阐述Java的基础知识点。 1. **Java简介** - Java是由Sun ...

    java io 与java nio区别

    为此,Java 1.4 版本引入了新的I/O处理方式——NIO,即New IO。NIO提供了一种基于通道(Channel)和缓冲区(Buffer)的新模型。 - **通道(Channel)**:可以理解为数据的双向通道,支持数据的读取和写入。 - **缓冲...

    黑马程序员入学Java知识——精华总结

    2. **类与对象**:Java是面向对象的,因此理解和创建类及对象是学习Java的关键。类是数据和操作这些数据的方法的集合,而对象是类的实例。封装、继承和多态是面向对象编程的三大特性。 3. **包与导入**:Java使用包...

    java面试——深圳-银盛支付-Java中级.zip

    这份"java面试——深圳-银盛支付-Java中级.zip"压缩包文件很可能包含了针对Java中级开发者的一系列面试问题和解答,旨在帮助求职者提升自己的技能,并在面试中脱颖而出。下面,我们将深入探讨一些可能涵盖的Java中级...

    Java学习材料(499篇文章)——Java学习材料(499篇文章)

    这份"Java学习材料(499篇文章)"的压缩包显然包含了大量关于Java学习的资源,旨在帮助初学者和有经验的开发者提升技能。下面将详细讨论Java的一些关键知识点。 1. **Java基础**: 包括变量、数据类型、运算符、控制...

    java面试——深圳-中国平安-Java中级.zip

    下面将根据"java面试——深圳-中国平安-Java中级.pdf"这份资料,提炼出一些核心的Java知识点。 1. **Java基础**: - **数据类型**:包括基本数据类型和引用数据类型,理解它们的区别和内存管理。 - **类与对象**...

    javaNIO学习笔记(csdn)————程序.pdf

    Java NIO,全称Non-Blocking Input/Output,是非阻塞式输入输出,它是Java从1.4版本开始引入的一种新的I/O模型,为Java程序员提供了处理I/O操作的新方式。NIO的主要特点是其能够使Java程序以更有效的方式处理I/O流,...

    java面试——杭州-蚂蚁金服-资深工程师.zip

    "java面试——杭州-蚂蚁金服-资深工程师.zip" 这个标题表明这是一份关于Java技术的面试准备资料,特别针对的是在杭州的蚂蚁金服公司应聘资深工程师的职位。这意味着这份压缩包可能包含了针对Java语言、高级编程技巧...

    java面试——杭州-阿里云-Java中级.zip

    这个压缩包文件“java面试——杭州-阿里云-Java中级.zip”包含了一份详细的PDF文档,它可能涵盖了面试中常遇到的问题、技术要点以及解决策略。以下是基于Java中级工程师面试的一些关键知识点: 1. **基础语法**:...

    javaNiO.doc

    为了解决这些问题,Java平台在JDK 1.4中引入了一个全新的I/O处理框架——NIO(New IO),即新I/O。本文将深入探讨传统I/O模型的问题,并详细介绍NIO的概念、优势以及其实现机制。 #### 2. 传统I/O模型及其局限性 ...

    Java JDK 6学习笔记——ppt简体版

    Java JDK 6学习笔记是为Java初学者量身定制的一份宝贵资料,它涵盖了Java编程的基础概念、语法以及核心特性。这份PPT简体版旨在帮助读者快速掌握Java开发的基本技能,逐步成为一名合格的Java程序员。 Java JDK...

    java面试——深圳-商汤科技-Java高级.zip

    7. **IO/NIO/BIO**:理解Java的输入输出模型,包括BufferedReader、FileInputStream等基本IO流,以及非阻塞IO(NIO)和BIO的区别和应用场景。 8. **网络编程**:理解TCP/IP协议,会编写Socket编程,了解HTTP协议,...

    高级JAVA面试——最全的总结

    2. **JAVA集合框架** - List、Set、Queue接口及其实现类:ArrayList、LinkedList、HashSet、LinkedHashSet、TreeSet、ArrayDeque等。 - Map接口及实现类:HashMap、TreeMap、LinkedHashMap、ConcurrentHashMap等,...

Global site tag (gtag.js) - Google Analytics