您的位置:首页 > 其它

Selector select方法阻塞register的解决方法

2015-07-03 11:29 387 查看
1. 监听端口, 当连接到来的时候创建socketChannel

public class MultiServer {

public static void main(String[] args) throws IOException {
ServerSocketChannel ss = ServerSocketChannel.open().bind(
new InetSocketAddress(8484));
final Selector selector = Selector.open();
wuTiRaw(selector);
while (true) {
SocketChannel channel = ss.accept();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ);
}
}

private static void wuTiRaw(final Selector selector) {
Thread t = new Thread(new Runnable() {

@Override
public void run() {
while (true) {
try {
selector.select();
Set<SelectionKey> keys = selector
.selectedKeys();
Iterator<SelectionKey> it = keys.iterator();
while (it.hasNext()) {
SelectionKey next = it.next();
if (next.isReadable()) {
ByteBuffer bb = ByteBuffer.allocate(10);
SocketChannel channel = (SocketChannel) next
.channel();
channel.read(bb);
System.out.println(bb.toString());

}
it.remove();
}
} catch (IOException e1) {
e1.printStackTrace();
}

}

}
});
t.start();
}


由于select方法与register 方法都需要获取相同的监视器,故上面的方法会一直阻塞在register方法上

解决如下:

public class MultiServer {

public static void main(String[] args) throws IOException {
ServerSocketChannel ss = ServerSocketChannel.open().bind(
new InetSocketAddress(8484));
final Selector selector = Selector.open();
SelectorHelper sh = new SelectorHelper(selector);
wuTi(sh);
while (true) {
SocketChannel channel = ss.accept();
channel.configureBlocking(false);
sh.reg(channel, SelectionKey.OP_READ);
}
}

private static void wuTi(final SelectorHelper selector) {
Thread t = new Thread(new Runnable() {

@Override
public void run() {
while (true) {
try {
selector.select();
Set<SelectionKey> keys = selector.getSelector()
.selectedKeys();
Iterator<SelectionKey> it = keys.iterator();
while (it.hasNext()) {
SelectionKey next = it.next();
if (next.isReadable()) {
ByteBuffer bb = ByteBuffer.allocate(10);
SocketChannel channel = (SocketChannel) next
.channel();
channel.read(bb);
System.out.println(bb.toString());

}
it.remove();
}
} catch (IOException e1) {
e1.printStackTrace();
}

}

}
});
t.start();
}

public static class SelectorHelper {
private volatile boolean mark = false;
private final Selector selector;

public SelectorHelper(Selector selector) {
this.selector = selector;
}

public Selector getSelector() {
return selector;
}

/**
* 必须是同步的, 保证多个线程调用reg的时候不会出现问题
* @param channel
* @param op
* @return
* @throws ClosedChannelException
*/
public synchronized SelectionKey reg(SelectableChannel channel, int op)
throws ClosedChannelException {
mark = true;
selector.wakeup();
SelectionKey register = channel.register(selector, op);
mark = false;
return register;
}

public int select() throws IOException {
for (;;) {
if (mark == true)
continue;
int select = selector.select();
if (select >= 1)
return select;
}
}
}
}


betty way:

public class MultiServer2 {
public static void main(String[] args) throws IOException {
ServerSocketChannel serverChannel = ServerSocketChannel.open()
.bind(new InetSocketAddress(8484));
Selector selector = Selector.open();
serverChannel.configureBlocking(false);
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
while(true) {
if(selector.select() == 0 ) continue;

Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> it = selectedKeys.iterator();
while(it.hasNext()) {
SelectionKey next = it.next();
it.remove();
handleReady(next, selector);
}
}
}

private static void handleReady(SelectionKey next, Selector selector) throws IOException {
if(next.isAcceptable()) {
ServerSocketChannel channel = (ServerSocketChannel)next.channel();
SocketChannel accept = channel.accept();
accept.configureBlocking(false);
accept.register(selector, SelectionKey.OP_READ);
}
if(next.isReadable()) {
ByteBuffer bb = ByteBuffer.allocate(10);
SocketChannel channel =(SocketChannel) next.channel();
channel.read(bb);
System.out.println(bb);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: