문제

실제 사례를 지적/제공해 주세요. selector.wakeup(); 두 스레드 사이의 방법.

스레드가 selector.select() 메서드를 기다리는 간단한 프로그램을 만들려고 했습니다.두 번째 스레드는 일부 소켓을 생성하고 선택기에 등록을 시도합니다.첫 번째 스레드가 차단됩니다.

따라서 선택기를 사용해야합니다 wakeup 방법을 사용했지만 첫 번째 스레드가 차단 모드에서 나오지 않습니다.

웨이크업 메소드의 javadoc은 다음과 같습니다:

셀렉터.select () 또는 selector.select (long) 메소드의 호출에서 다른 스레드가 차단되면 해당 호출이 즉시 돌아옵니다.

추신 다른 해결 방법은 거의 없습니다.그 중 하나가 select(timeout)인데 어디에서 실수가 발생했는지 알아내려고 노력 중입니다.

유사 코드:

첫 번째 스레드:

static Selector selector = Selector.open();
while(true) {
   int n = selectorGlobal.select();
   selectorKeySet = selectorGlobal.selectedKeys().iterator();
   while (selectorKeySet.hasNext()) {
      selectionKey = selectorKeySet.next();
      if (selectionKey.isReadable()) {
         //do something
      }
      if(selectionKey.isAcceptable()) {
         //accept
      }
   }
}

두 번째 스레드:

while (itr.hasNext()) { 
   data = (String) itr.next();
   String IP = data.get(0);
   String Port = data.get(1);

   SocketChannel socketChannel = SocketChannel.open();
   socketChannel.configureBlocking(true);
   boolean isConnected = socketChannel.connect(new InetSocketAddress(IP, Port));
   ClassName.selector.wakeup();
   SelectionKey selectionKey = SelectSockets.registerChannel(ClassName.selector,
                socketChannel, SelectionKey.OP_READ);

}
도움이 되었습니까?

해결책

선택기에 등록하는 경우 스레드 2의 소켓이 차단되는 것을 원하지 않을 것입니다(선택기는 비차단 I/O를 위한 것이므로).선택기가 OP_CONNECT(SocketChannel.finishConnection() 사용)와의 연결을 처리하도록 하는 것도 일반적인 관행이라고 생각합니다.

또한 여기에 잠재적인 경쟁 조건이 있을 수 있는 것처럼 보입니다.다음과 같은 일련의 이벤트를 상상해 보세요.

  1. 스레드 1:선택기.선택()
  2. ...시간이 흐르다 ...
  3. 스레드 2:Thread1.selector.wakeup()
  4. 스레드 1:키의 허용 여부를 확인합니다.
  5. 스레드 1:키의 가독성을 확인합니다.
  6. 스레드 1:고리
  7. 스레드 1:선택기.선택()
  8. 스레드 2:선택기에 등록을 시도합니다(그러나 이 select()에는 너무 늦었습니다).

나는 스레드 2가 SocketChannel을 설정하고 스레드 1이 접근할 수 있는 어딘가에 그것을 숨긴 다음(이 작업을 수행할 때 스레드로부터 안전한지 확인) 선택기를 깨우고 스레드 1에 기존 키가 있는지 확인하도록 제안합니다. 스레드 1이 Selector.select()를 다시 호출하기 전에 새 SocketChannel을 등록하도록 합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top