• IO用法几例


    http://tutorials.jenkov.com/java-nio/buffers.html

    IO

    一个例子

    public class DemoServer extends Thread {
        private ServerSocket serverSocket;
    
        public int getPort() {
            return serverSocket.getLocalPort();
        }
    
        @Override
        public void run() {
            try {
                serverSocket = new ServerSocket(0);    // 绑定0端口
                while (true) {
                    Socket socket = serverSocket.accept();      // 调用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) {
            DemoServer server = new DemoServer();
            server.start();        
            try (Socket client = new Socket(InetAddress.getLocalHost(), server.getPort())) {    // 模拟socket客户端
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(client.getInputStream()));
                bufferedReader.lines().forEach(s -> System.out.println(s));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    class RequestHandler extends Thread {
        private Socket socket;
        RequestHandler(Socket socket) {
            this.socket = socket;
        }
    
        @Override
        public void run() {
            try (PrintWriter out = new PrintWriter(socket.getOutputStream());) {
                out.println("hello");
                out.flush();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    线程启动

    每个都开一个线程过于浪费,线程池改进

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

    并发量不大的情况这种同步阻塞方式是可以的,但是由于线程的上下文切换是废性能的,在高并发情况下显然不合适。

    NIO例子

    public class NIOServer extends Thread {
    
        @Override
        public void run() {
            try (Selector selector = Selector.open();
                 ServerSocketChannel serverSocket = ServerSocketChannel.open();) {
                serverSocket.bind(new InetSocketAddress(InetAddress.getLocalHost(), 8888));
                serverSocket.configureBlocking(false);
                serverSocket.register(selector, SelectionKey.OP_ACCEPT);
                while (true) {
                    selector.select();
                    Set<SelectionKey> selectionKeys = selector.selectedKeys();
                    Iterator<SelectionKey> iter = selectionKeys.iterator();
                    while (iter.hasNext()) {
                        SelectionKey key = iter.next();
                        sayHello((ServerSocketChannel) key.channel());
                        iter.remove();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        private void sayHello(ServerSocketChannel server) {
            try (SocketChannel client  = server.accept()) {
                client.write(Charset.defaultCharset().encode("hello"));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    NIO利用了单线程轮询事件的机制,通过高效地定位就绪的Channel,来决定做什 么,仅仅select阶段是阻塞的,可以有效避免大量客户端连接时,频繁线程切换带来的问题,应用的扩展能力有了非常大的提高。下面这张图对这种实现思路进行了形象地说明。

    NIO2,异步IO

    通过指定CompletionHandler回调接口,在accept/read/write等关键节点,通过事件机制调用。

    文件拷贝

            try (InputStream inputStream = new FileInputStream(source);
                 OutputStream outputStream = new FileOutputStream(dest)) {
                byte[] buffer = new byte[1024];
                int length;
                while ((length = inputStream.read(buffer)) > 0) {
                    outputStream.write(buffer, 0, length);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try (FileChannel sourceChanel = new FileInputStream(source).getChannel();
                FileChannel targetChanel = new FileOutputStream(dest).getChannel()) {
                for (long count = sourceChanel.size(); count > 0; ) {
                    long transferred = sourceChanel.transferTo(sourceChanel.position(),
                            count, targetChanel);
                    sourceChanel.position(sourceChanel.position() + transferred);
                    count -= transferred;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

    end

    参照第一个链接可练习。

    一个没有高级趣味的人。 email:hushui502@gmail.com
  • 相关阅读:
    为什么GNU grep如此之快?
    在百度nlp实习一个月时间里用到的shell操作
    InfoPi简介、试用链接、资料索引
    自定义worker的方法,及一例
    2017.1.9版给信息源新增:max_len、max_db字段
    手把手写一个html_json信息源
    定义信息源的一些示例(xml文件)
    启用https协议的方法
    安装第三方Python模块,增加InfoPi的健壮性
    更新日志(建议升级到2017.1.18a) && 更新程序的方法
  • 原文地址:https://www.cnblogs.com/CherryTab/p/12170855.html
Copyright © 2020-2023  润新知