Sono abbastanza appassionato di Java NIO e voglio davvero applicare Java NIO al mio sistema attuale, ma quando ho creato questi esempi di applicazioni per confrontare tra Java IO e NIO, mi ha fatto molto deludere.Java IO vs NIO, qual è la differenza?
Qui ci sono i miei 2 campioni (non metto tutto il codice sorgente)
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);
}
}
}
client
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);
}
}
}
}
Il client durante l'esecuzione verrà creato e 10 client si connettono al server. Dopo essere stato eseguito e monitorato più volte, non ho trovato differenze tra Java IO e NIO.
Se il numero di clienti cambiato a 500, ho trovato che il java IO veramente creato 500 discussioni, ma il consumo di dati veramente veloce. Al contrario, l'applicazione NIO Java aveva un numero di thread molto inferiore rispetto all'altro, ma il consumo di dati era lento e ci voleva più tempo per completare tutto.
Quindi, qual è il vantaggio di Java NIO? Crea meno thread per risparmiare memoria, ma rallentando le prestazioni.
Oppure, potrei farlo in modo errato.
Come menzionato [qui] (https://stackoverflow.com/q/46965752/3317808), NIO- non bloccante IO, è un singolo modello di programmazione filettato che coinvolge selezionare() '' chiamata di sistema internamente. Non sono sicuro, perché confrontiamo l'I/O bloccato con thread con NIO con thread. – overexchange