문제
실제 사례를 지적/제공해 주세요. 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:선택기.선택()
- ...시간이 흐르다 ...
- 스레드 2:Thread1.selector.wakeup()
- 스레드 1:키의 허용 여부를 확인합니다.
- 스레드 1:키의 가독성을 확인합니다.
- 스레드 1:고리
- 스레드 1:선택기.선택()
- 스레드 2:선택기에 등록을 시도합니다(그러나 이 select()에는 너무 늦었습니다).
나는 스레드 2가 SocketChannel을 설정하고 스레드 1이 접근할 수 있는 어딘가에 그것을 숨긴 다음(이 작업을 수행할 때 스레드로부터 안전한지 확인) 선택기를 깨우고 스레드 1에 기존 키가 있는지 확인하도록 제안합니다. 스레드 1이 Selector.select()를 다시 호출하기 전에 새 SocketChannel을 등록하도록 합니다.