2014-07-07 9 views
6

मैं जावा एनआईओ का बहुत शौकिया हूं और मैं वास्तव में अपने वर्तमान सिस्टम में जावा एनआईओ लागू करना चाहता हूं, लेकिन जब मैंने जावा आईओ और एनआईओ के बीच तुलना करने के लिए इन नमूनों के आवेदन को बनाया, तो इससे मुझे काफी निराशा हुई।जावा आईओ बनाम एनआईओ, वास्तव में क्या अंतर है?

यहाँ मेरी 2 नमूने हैं (मैं सभी स्रोत कोड डाल नहीं)

जावा आईओ

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 { 
       ..... 
      } 
     } 
    } 
} 

जावा 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); 
      } 
     } 
    } 
} 

जब ग्राहक चलाएगा क्लाइंट ई 10 क्लाइंट सर्वर से कनेक्ट हैं। कई बार चलाने और निगरानी करने के बाद, मुझे जावा आईओ और एनआईओ के बीच कोई अलग नहीं मिला।

यदि 500 ​​की संख्या में ग्राहकों की संख्या बदल गई, तो मैंने पाया कि जावा आईओ ने वास्तव में 500 धागे बनाए हैं, हालांकि डेटा की खपत वास्तव में तेज़ है। इसके विपरीत, जावा एनआईओ अनुप्रयोग में दूसरे की तुलना में बहुत कम धागे थे, लेकिन डेटा की खपत धीमी थी और सब कुछ खत्म करने में लंबा समय लगा।

तो, वास्तव में जावा एनआईओ का क्या फायदा है? स्मृति को बचाने के लिए कम धागे बनाएं लेकिन प्रदर्शन में धीमे हो जाएं।

या, मैंने गलत तरीके से ऐसा किया होगा।

उत्तर

6

आप जिस गति अंतर को देख रहे हैं वह 4s नींद की वजह से है जो दोनों परीक्षण मामलों में दिखाई देता है।

गैर-एनआईओ मामले में, जिसमें प्रति अनुरोध एक धागा है, 4 सेकंड के लिए सोना केवल एक अनुरोध को अवरुद्ध करता है। हालांकि NIO मामले, जो कार्यकर्ता धागे के एक दूर छोटी संख्या है, यह ब्लॉक कि अनुरोध और हर दूसरे अनुरोध है कि उस धागे पर चलाने के लिए इंतज़ार कर रहा है है में।

तो यह सवाल पूछता है, हम एनआईओ दृष्टिकोण के साथ कम धागे का उपयोग क्यों करना चाहते हैं? और जवाब स्केलेबिलिटी है। आधुनिक ऑपरेटिंग सिस्टम में नेटवर्क IO पर अवरुद्ध धागे की संख्या से संबंधित एक स्केलिंग समस्या है। अधिक जानकारी के लिए C10K समस्या देखें।

सामान्य तौर पर मैं NIO तेजी से होने के लिए मिल रहा है, या कम से कम यह क्षमता है, तो बहुत तेजी से होने के लिए:

  1. आप इसका इस्तेमाल के आसपास नकल बफ़र्स
  2. से बचने के लिए और अगर आप कुछ भी है कि यह कर सकते हैं से बचने धागे को ब्लॉक करें। जैसे एक डेटाबेस पर को ब्लॉक नहीं करती लाने आदि

यह जहां akka चमक की तरह async चौखटे है।

+0

जैसा कि बताया जा [यहां] (https://stackoverflow.com/q/46965752/3317808), NIO- गैर आईओ को अवरुद्ध, एक एकल थ्रेड प्रोग्रामिंग मॉडल है कि आंतरिक रूप से 'का चयन करें()' सिस्टम कॉल किया जाता है। मुझे यकीन नहीं है, हम थ्रेडेड एनआईओ के साथ थ्रेडेड अवरुद्ध आईओ की तुलना क्यों करते हैं। – overexchange

संबंधित मुद्दे