2014-07-07 74 views
6

我非常喜歡Java NIO,並且我非常想將Java NIO應用到我當前的系統中,但是當我創建這些示例應用程序來比較Java IO和NIO時,它讓我頗感失望。Java IO vs NIO,真的有什麼區別?

這裏是我的2個樣本(我不把所有的源代碼)

的Java IO

public class BlockingServerClient { 

    private static final Logger log = Logger.getLogger(BlockingServerClient.class.getName()); 

    static final ExecutorService service = Executors.newCachedThreadPool(); 

    public static void main(String[] args) throws InterruptedException { 
     int port = Integer.parseInt(args[0]); 

     BlockingServerClient server = new BlockingServerClient(); 

     Server sr = server.new Server(port); 
     service.submit(sr); 
    } 

    private class Server implements Runnable { 

     ..... 

     public void run() { 
      ServerSocket ss = null; 
      try { 
       ss = new ServerSocket(localPort); 
       log.info("Server socket bound to " + localPort); 

       while (true) { 
        Socket client = ss.accept(); 
        log.info("Accepted connection from " + client.getRemoteSocketAddress()); 

        service.submit(new SocketClient(client)); 
       } 

      } catch (IOException e) { 
       log.log(Level.SEVERE, "Server error", e); 
      } finally { 
       ..... 
      } 
     } 
    } 

    private class SocketClient implements Runnable { 

     ..... 

     public void run() { 
      InetSocketAddress addr = (InetSocketAddress) socket.getRemoteSocketAddress(); 
      socketInfo = String.format("%s:%s", addr.getHostName(), addr.getPort()); 

      log.info("Start reading data from " + socketInfo); 
      try { 
       in = new BufferedReader(
         new InputStreamReader(socket.getInputStream())); 

       String input; 
       while ((input = in.readLine()) != null) { 
        log.info(String.format("[%s] %s", socketInfo, input)); 

        log.info("Socket " + socketInfo + " thread sleep 4s"); 
        TimeUnit.SECONDS.sleep(4); 
       } 

      } catch (Exception ex) { 
       log.log(Level.SEVERE, "Socket error", ex); 
      } finally { 
       ..... 
      } 
     } 
    } 
} 

的Java NIO

public class NonBlockingServerClient { 

    private static final Logger log = Logger.getLogger(NonBlockingServerClient.class.getName()); 

    public static void main(String[] args) { 
     int port = Integer.parseInt(args[0]); 

     EventLoopGroup boss = new NioEventLoopGroup(); 
     EventLoopGroup worker = new NioEventLoopGroup(); 

     try { 
      NonBlockingServerClient sc = new NonBlockingServerClient(); 

      Server server = sc.new Server(port, boss, worker); 

      server.run(); 

     } catch (Exception e) { 
      log.log(Level.SEVERE, "Error", e); 
     } finally { 
      boss.shutdownGracefully(); 
      worker.shutdownGracefully(); 
     } 
    } 

    private class Server { 

     ..... 

     public void run() { 
      log.info("Start Server bootstrap"); 
      ServerBootstrap b = new ServerBootstrap(); 
      b.group(boss, worker) 
      .channel(NioServerSocketChannel.class) 
      .childHandler(new ChannelInitializer<Channel>() { 

       @Override 
       protected void initChannel(Channel ch) throws Exception { 
        ChannelPipeline pipe = ch.pipeline(); 
        pipe.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); 
        pipe.addLast(new StringDecoder()); 
        pipe.addLast(new ClientHandler()); 
       } 
      }); 

      ChannelFuture future = null; 
      try { 
       future = b.bind(port).sync(); 
       future.channel().closeFuture().sync(); 
      } catch (InterruptedException e) { 
       log.log(Level.SEVERE, "Server binding error", e); 
       future.channel().close(); 
      } 

     } 
    } 

    private class ClientHandler extends SimpleChannelInboundHandler<String> { 

     @Override 
     protected void channelRead0(ChannelHandlerContext ctx, String msg) 
       throws Exception { 
      log.info(String.format("[%s] %s", ctx.channel().remoteAddress(), msg)); 
      log.info(ctx.channel().remoteAddress() + " sleep 4s"); 
      TimeUnit.SECONDS.sleep(4); 
     } 

    } 
} 

客戶

public class Client { 

    private static final Logger log = Logger.getLogger(Client.class.getName()); 

    public static void main(String[] args) throws InterruptedException { 
     int port = Integer.parseInt(args[0]); 

     for (int i = 0; i < 10; i++) { 
      Client cl = new Client("localhost", port); 
      cl.start(); 
      TimeUnit.MILLISECONDS.sleep(500); 
     } 
    } 

    String host; 
    int port; 

    public Client(String host, int port) { 
     this.host = host; 
     this.port =port; 
    } 

    public void start() { 
     log.info("Start client running"); 
     Socket socket = null; 
     String info = ""; 
     try { 
      socket = new Socket(host, port); 
      InetSocketAddress addr = (InetSocketAddress) socket.getLocalSocketAddress(); 
      info = String.format("%s:%s", addr.getHostName(), addr.getPort()); 
      int count = 10; 

      OutputStream out = socket.getOutputStream(); 
      while (count > 0) { 
       String outStr = "Output-" + count + "\n"; 
       out.write(outStr.getBytes()); 
       out.flush(); 
       count--; 
      } 
      out.write((info + "-Finish sending").getBytes()); 
      out.flush(); 
     } catch (Exception e) { 
      log.log(Level.SEVERE, "Client error", e); 
     } finally { 
      try { 
       socket.close(); 
       log.info(info + "-Client close"); 
      } catch (IOException e) { 
       log.log(Level.SEVERE, "Closing client error", e); 
      } 
     } 
    } 
} 

運行時客戶端將創建e 10個客戶端連接到服務器。在我運行並監控了好幾次之後,我發現Java IO和NIO沒有什麼不同。

如果將客戶端數量更改爲500,我發現Java IO確實創建了500個線程,但數據消耗非常快。相比之下,Java NIO應用程序比另一個應用程序的線程少得多,但數據消耗很慢,完成所有操作需要較長的時間。

那麼,Java NIO有什麼好處呢?創建更少的線程來節省內存,但性能更慢。

或者,我可能做錯了。

回答

6

您注意到的速度差異是由於兩個測試用例中出現的4s睡眠。

在非NIO的情況下,每個請求有一個線程,睡眠4秒只阻塞一個請求。但是在工作線程數量少得多的NIO情況下,它會阻止該請求以及等待在該線程上運行的其他每個請求。

因此,這引出了一個問題,爲什麼我們要用NIO方法少用線程?答案是可擴展性。現代操作系統有一個擴展問題,與網絡IO上被阻塞的線程數有關。有關更多詳細信息,請參閱C10K問題。

總的來說,我確實發現NIO要快一些,或者至少是有潛力,如果要快得多:

  1. 您可以使用它來避免各地複製緩衝區
  2. 你避免任何可能阻止線程。例如,不要在數據庫上阻止 取等

這是異步框架,如akka光澤。

+0

正如[here](https://stackoverflow.com/q/46965752/3317808)所述,NIO-非阻塞IO是一種單線程編程模型,它在內部包含'select()'系統調用。我不確定,爲什麼我們將線程阻塞的IO與線程化的NIO進行比較。 – overexchange

相關問題