Java NIO.2 CompletetionHandler 未到达

标签 java multithreading sockets asynchronous nio2

Java NIO.2 大师可以解释为什么当我注释掉 Thread.sleep(...) 行时这段代码不起作用。

告诉 JVM 处理异步操作直到程序完成的优雅方法是什么?

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;

public class Main {
    public static void main(String[] args) {
        try {
            AsynchronousSocketChannel channel = AsynchronousSocketChannel.open();
            channel.connect(new InetSocketAddress("www.yahoo.com", 80),
                    null, new CompletionHandler<Void, Object>() {
                        @Override
                        public void completed(Void result, Object attachment) {
                            System.out.println("Connected");

                            ByteBuffer buffer = ByteBuffer.wrap("GET http://www.yahoo.com HTTP/1.1\r\n\r\n".getBytes());
                            channel.write(buffer, null, new CompletionHandler<Integer, Object>() {
                                @Override
                                public void completed(Integer result, Object attachment) {
                                    System.out.println("Write completed: " + result.toString());

                                    ByteBuffer buffer = ByteBuffer.allocate(23);

                                    channel.read(buffer, null, new CompletionHandler<Integer, Object>() {
                                        @Override
                                        public void completed(Integer result, Object attachment) {
                                            System.out.println("Read completed: " + result.toString());
                                            System.out.println(new String(buffer.array()));
                                        }

                                        @Override
                                        public void failed(Throwable exc, Object attachment) {
                                            exc.printStackTrace();
                                        }
                                    });
                                }

                                @Override
                                public void failed(Throwable exc, Object attachment) {
                                    exc.printStackTrace();
                                }
                            });
                        }

                        @Override
                        public void failed(Throwable exc, Object attachment) {
                            exc.printStackTrace();
                        }
                    });

            Thread.sleep(10000);

            channel.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

提前致谢。

最佳答案

为什么当 Thread.sleep(...) 被删除时它不起作用:

方法connect(SocketAddress remote, A attachment, CompletionHandler<Void,? super A> handler)创建一个新线程,在其中连接并调用处理程序。

因此,您无需延迟即可在连接或传输所有数据之前关闭套接字。

如何避免

你必须找到一种方法来等待其他线程。

例如 java.util.concurrent.CompletableFuture<V> :

try {
    CompletableFuture<Boolean> future = new CompletableFuture<Boolean>();

    AsynchronousSocketChannel channel = AsynchronousSocketChannel.open();
    channel.connect(new InetSocketAddress("www.yahoo.com", 80),
            null, new CompletionHandler<Void, Object>() {
                @Override
                public void completed(Void result, Object attachment) {
                    System.out.println("Connected");

                    ByteBuffer buffer = ByteBuffer.wrap("GET http://www.yahoo.com HTTP/1.1\r\n\r\n".getBytes());
                    channel.write(buffer, null, new CompletionHandler<Integer, Object>() {
                        @Override
                        public void completed(Integer result, Object attachment) {
                            System.out.println("Write completed: " + result.toString());

                            ByteBuffer buffer = ByteBuffer.allocate(23);

                            channel.read(buffer, null, new CompletionHandler<Integer, Object>() {
                                @Override
                                public void completed(Integer result, Object attachment) {
                                    System.out.println("Read completed: " + result.toString());
                                    System.out.println(new String(buffer.array()));

                                    // 
                                    future.complete(true);
                                }

                                @Override
                                public void failed(Throwable exc, Object attachment) {
                                    exc.printStackTrace();
                                    //
                                    future.complete(false);
                                }
                            });
                        }

                        @Override
                        public void failed(Throwable exc, Object attachment) {
                            exc.printStackTrace();
                            //
                            future.complete(false);
                        }
                    });
                }

                @Override
                public void failed(Throwable exc, Object attachment) {
                    exc.printStackTrace();
                    //
                    future.complete(false);
                }
            });
    // Wait until the other Threads are finished
    System.out.println("Successs: "+future.get(10, TimeUnit.SECONDS));
    channel.close();
} catch (Exception ex) {
    ex.printStackTrace();
}

或者在您的情况下,您可以简单地处理 AsynchronousSocketChannel这样(没有处理程序):

    try {
    AsynchronousSocketChannel channel = AsynchronousSocketChannel.open();
    Future<Void> futureConnect = channel.connect(new InetSocketAddress("www.yahoo.com", 80));
    // wait until connected
    futureConnect.get();
    System.out.println("Connected");

    ByteBuffer buffer = ByteBuffer.wrap("GET http://www.yahoo.com HTTP/1.1\r\n\r\n".getBytes());
    Future<Integer> futureWrite = channel.write(buffer);
    // wait until all data is written
    Integer resultWrite = futureWrite.get();
    System.out.println("Write completed: " + resultWrite.toString());

    ByteBuffer bufferRead = ByteBuffer.allocate(23);
    Future<Integer> futureRead = channel.read(bufferRead);
    // wait ...
    Integer resultRead = futureRead.get();
    System.out.println("Read completed: " + resultRead.toString());
    System.out.println(new String(bufferRead.array()));

    // finnished now the channel can be closed
    channel.close();
} catch (Exception e) {
    e.printStackTrace();
}

关于Java NIO.2 CompletetionHandler 未到达,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44325231/

相关文章:

Java 和 python 没有获得相同的 sha-1 值

java - 如何以安全且可读的方式处理我知道永远不会抛出的 IOException?

c++ - 如何消除并行 std::transform_reduce() 的中间容器?

multithreading - 在多核 x86 上,是否需要将 LOCK 作为 XCHG 的前缀?

java - 在服务中配置线程池大小

java - 缺少来自套接字的数据

java - 如何找到远程系统的 CPU 负载

Python ssl 获取支持的密码

node.js - socket.io NodeJS Express 和 mqtt

java - Android 计算器中不使用变量