2017-06-02 43 views
1

Java NIO.2 Gurus任何人都可以解釋爲什麼當我註釋掉Thread.sleep(...)行時,此代碼無法工作。Java NIO.2 CompletetionHandler未達到

什麼是優雅的方式,告訴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(); 
     } 
    } 
} 

在此先感謝。

回答

1

爲什麼當了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(); 
}