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

来源:互联网 发布:西安广电网络电视台 编辑:程序博客网 时间:2024/06/03 21:22

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() {@Overridepublic 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() {@Overridepublic 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);}}}


0 0