Java NIO-선택기

Java NIO는 채널과 버퍼에 대한 다중 트랜잭션을 지원한다는 것을 알고 있습니다. 따라서 하나 이상의 NIO 채널을 검사하고 데이터 트랜잭션을 위해 준비된 채널 (예 : Java NIO 읽기 또는 쓰기)을 결정하기 위해 Selector를 제공합니다.

Selector를 사용하면 어떤 채널이 데이터 쓰기 및 읽기 준비가되었는지 알 수있는 스레드를 만들고 해당 특정 채널을 처리 할 수 ​​있습니다.

정적 메서드를 호출하여 선택기 인스턴스를 얻을 수 있습니다. open()오픈 셀렉터 후에 우리는 SelectionKey의 인스턴스를 반환하는 비 차단 모드 채널을 등록해야합니다.

SelectionKey는 기본적으로 채널로 수행 할 수있는 작업 모음이거나 선택 키를 사용하여 채널의 상태를 알 수 있다고 말할 수 있습니다.

선택 키로 표시되는 주요 작업 또는 채널 상태는 다음과 같습니다.

  • SelectionKey.OP_CONNECT − 서버에 연결할 준비가 된 채널.

  • SelectionKey.OP_ACCEPT − 들어오는 연결을 수락 할 준비가 된 채널.

  • SelectionKey.OP_READ − 데이터를 읽을 준비가 된 채널.

  • SelectionKey.OP_WRITE − 데이터 쓰기 준비가 된 채널.

등록 후 얻은 선택 키에는 아래에 언급 된 몇 가지 중요한 방법이 있습니다.

  • attach() − 키로 오브젝트를 붙이는 방법으로, 오브젝트를 채널에 붙이는 주된 목적은 동일한 채널을 인식하는 것입니다.

  • attachment() −이 방법은 채널에서 부착 된 개체를 유지하는 데 사용됩니다.

  • channel() −이 방법은 특정 키가 생성 된 채널을 가져 오는 데 사용됩니다.

  • selector() −이 방법은 특정 키가 생성 된 선택자를 가져 오는 데 사용됩니다.

  • isValid() −이 메서드는 키가 유효한지 날씨를 반환합니다.

  • isReadable() −이 방법은 날씨 키의 채널을 읽을 준비가되었는지 여부를 나타냅니다.

  • isWritable() −이 방법은 날씨 키의 채널이 쓰기 준비가되었는지 여부를 나타냅니다.

  • isAcceptable() −이 방법은 날씨 키의 채널이 수신 연결을 수락 할 준비가되었는지 여부를 나타냅니다.

  • isConnectable() −이 메서드는이 키의 채널이 소켓 연결 작업을 완료했는지 또는 완료하지 못했는지 테스트합니다.

  • isAcceptable() −이 메서드는이 키의 채널이 새 소켓 연결을 수락 할 준비가되었는지 여부를 테스트합니다.

  • interestOps() −이 방법은이 키의 관심 세트를 검색합니다.

  • readyOps() −이 방법은 채널이 준비된 작업 세트 인 준비 세트를 검색합니다.

선택기에서 정적 메서드를 호출하여 채널을 선택할 수 있습니다. select(). 선택기의 선택 방법은 다음과 같이 과부하됩니다.

  • select() −이 메서드는 등록 된 이벤트에 대해 하나 이상의 채널이 준비 될 때까지 현재 스레드를 차단합니다.

  • select(long timeout) −이 메서드는 최대 타임 아웃 밀리 초 (파라미터) 동안 스레드를 차단한다는 점을 제외하면 select ()와 동일합니다.

  • selectNow() −이 메서드는 전혀 차단하지 않으며 준비된 채널이 있으면 즉시 반환합니다.

또한 select 메서드를 호출하는 차단 된 스레드를 떠나기 위해wakeup() 메서드는 selector 인스턴스에서 호출 될 수 있으며 그 후에 select () 내부에서 대기중인 스레드가 즉시 반환됩니다.

마지막으로 다음을 호출하여 선택기를 닫을 수 있습니다. close() 선택기를 닫고이 선택기에 등록 된 모든 SelectionKey 인스턴스를 무효화하는 메서드입니다.

import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class SelectorDemo {
   public static void main(String[] args) throws IOException {
      String demo_text = "This is a demo String";	
      Selector selector = Selector.open();
      ServerSocketChannel serverSocket = ServerSocketChannel.open();
      serverSocket.bind(new InetSocketAddress("localhost", 5454));
      serverSocket.configureBlocking(false);
      serverSocket.register(selector, SelectionKey.OP_ACCEPT);
      ByteBuffer buffer = ByteBuffer.allocate(256);
      while (true) {
         selector.select();
         Set<SelectionKey> selectedKeys = selector.selectedKeys();
         Iterator<SelectionKey> iter = selectedKeys.iterator();
         while (iter.hasNext()) {
            SelectionKey key = iter.next();
            int interestOps = key.interestOps();
            System.out.println(interestOps);
            if (key.isAcceptable()) {
               SocketChannel client = serverSocket.accept();
               client.configureBlocking(false);
               client.register(selector, SelectionKey.OP_READ);
            }
            if (key.isReadable()) {
               SocketChannel client = (SocketChannel) key.channel();
               client.read(buffer);
               if (new String(buffer.array()).trim().equals(demo_text)) {
                  client.close();
                  System.out.println("Not accepting client messages anymore");
               }
               buffer.flip();
               client.write(buffer);
               buffer.clear();
            }
            iter.remove();
         }
      }
   }
}