我有一個子類Thread
與私人Selector
和一個公衆register(SelectableChannel channel, ...)
方法,允許其他線程註冊通道到選擇器。NIO Selector:如何正確註冊新頻道,同時選擇
由於在回答here,通道的register()
塊選擇的select()
/select(long timeout)
所以我們需要wakeup()
選擇。
我的線程無限期選擇(除非它被中斷),它實際上設法調用通道的register()
之前進入下一個選擇。所以我想我使用塊的簡單鎖定來確保register()
首先發生。
代碼:(不相關的代碼的可讀性刪除)
public class SelectorThread extends Thread {
...
public void register(SelectableChannel channel, Attachment attachment) throws IOException {
channel.configureBlocking(false);
synchronized (this) { // LOCKING OCCURS HERE
selector.wakeup();
channel.register(selector,
SelectionKey.OP_READ,
attachment);
}
}
@Override
public void run() {
int ready;
Set<SelectionKey> readyKeys;
while (!isInterrupted()) {
synchronized (this) {} // LOCKING OCCURS HERE
try {
ready = selector.select(5000);
} catch (IOException e) {
e.printStackTrace();
continue;
}
if (ready == 0) {
continue;
}
readyKeys = selector.selectedKeys();
for (SelectionKey key : readyKeys) {
readyKeys.remove(key);
if (!key.isValid()) {
continue;
}
if (key.isReadable()) {
...
}
}
}
}
}
這個簡單的鎖允許register()
到線程繼續下一個選擇循環之前發生。據我測試,這按預期工作。
問題: 這是一個「好」的方式來做到這一點,或者是否有任何嚴重的缺點呢?使用列表或隊列(如建議here)來存儲註冊通道,還是使用更復雜的鎖,如this,會更好嗎?那是什麼優點/缺點?或者有什麼「更好」的方法?
在調用select()的同時向選擇器註冊通道時Java線程塊可能重複。該怎麼辦?](https://stackoverflow.com/questions/1057224/java-thread-blocks-while-registering-channel-with-selector-while-select-is-cal) – Flow