java selector bug_【记录】Java NIO实现网络模块遇到的BUG

public classNonblockingServer {/**处理客户端读写*/

privateSelectorThread[] selectorThreads;/**建立新连接*/

privateAcceptThread acceptThread;/**选择器*/

privateSelectNextSelectorThread nextSelectorThread;/**默认selectorThread数量*/

private static int defaultSelectorNum = 3;publicNonblockingServer() {this(defaultSelectorNum);

}public NonblockingServer(intselectorThreadNum) {if (selectorThreadNum < 1) {throw new IllegalArgumentException("SelectorThread线程数量不能低于1");

}

selectorThreads= newSelectorThread[selectorThreadNum];try{for (int i = 0; i < selectorThreads.length; i++) {

selectorThreads[i]= new SelectorThread("selector-thread-" +i);

}

acceptThread= new AcceptThread("accept-thread");

nextSelectorThread= newSelectNextSelectorThread(Arrays.asList(selectorThreads));

}catch(Exception e) {throw newRuntimeException(e);

}

}public void listen(String host, intport) {try{

acceptThread.listen(host, port);

}catch(IOException e) {throw newRuntimeException(e);

}

}/*** 处理连接事件,把新连接注册到一个SelectorThread上*/

class AcceptThread extendsThread {privateSelector selector;privateServerSocketChannel serverChannel;

AcceptThread(String name)throwsIOException {super(name);

selector=Selector.open();

}public void listen(String host, int port) throwsIOException {

serverChannel=ServerSocketChannel.open();

serverChannel.configureBlocking(false);

serverChannel.register(selector, SelectionKey.OP_ACCEPT);

serverChannel.bind(newInetSocketAddress(host, port));this.start();

}

@Overridepublic voidrun() {while (!Thread.currentThread().isInterrupted()) {try{int select =selector.select();if (select == 0) {continue;

}

Set keys =selector.selectedKeys();

Iterator iterator =keys.iterator();while(iterator.hasNext()) {

SelectionKey key=iterator.next();

iterator.remove();if(key.isAcceptable()) {

handAccept();

}

}

}catch(Exception e) {

e.printStackTrace();

}

}

}private void handAccept() throwsIOException {

SocketChannel clientChannel=serverChannel.accept();

SelectorThread selectorThread=nextSelectorThread.nextThread();//懒加载

if (!selectorThread.isStart()) {

selectorThread.start();

}

selectorThread.register(clientChannel);

}

}/*** 处理客户端连接的读/写事件*/

class SelectorThread extendsThread {privateSelector selector;private BlockingQueuetasks;private volatile boolean start = false;

SelectorThread(String name)throwsIOException {super(name);

selector=Selector.open();

tasks= new LinkedBlockingQueue<>();

}

@Overridepublic voidrun() {while(start) {try{

selector.select();

handTask();

Set keys =selector.selectedKeys();

Iterator iterator =keys.iterator();while (start &&iterator.hasNext()) {

SelectionKey key=iterator.next();

iterator.remove();

SocketChannel channel=(SocketChannel) key.channel();if(key.isReadable()) {

handRead(channel);

}else if(key.isWritable()) {

handWrite(channel);

}

}

}catch(Exception e) {

e.printStackTrace();

}

}

}private voidhandTask() {

Runnable task;while (start && (task = tasks.poll()) != null) {

task.run();

}

}/*** 这里简单的把输出打印出来*/

private void handRead(SocketChannel channel) throwsIOException {

ByteBuffer buffer= ByteBuffer.allocate(1024);int read =channel.read(buffer);if (read == -1) {

System.out.println(channel.getRemoteAddress()+ " 断开连接");

channel.close();

}else{byte[] bytes = new byte[read];

buffer.flip();

buffer.get(bytes);

System.out.println(newString(bytes));

buffer.clear();

}

}private voidhandWrite(SocketChannel channel) {//nothing

}/*** 把新连接注册到本线程*/

public voidregister(SocketChannel clientChannel) {

submit(()->{try{

clientChannel.configureBlocking(false);

clientChannel.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE);

}catch(Exception e) {try{

clientChannel.close();

}catch(IOException ex) {

ex.printStackTrace();

}

}

});

selector.wakeup();

}public voidsubmit(Runnable task) {

tasks.offer(task);

}

@Overridepublic synchronized voidstart() {

start= true;super.start();

}public voidshutdown() {this.start = false;this.interrupt();

}public booleanisStart() {returnstart;

}

}static classSelectNextSelectorThread {private final Collection extends SelectorThread>threads;private Iterator extends SelectorThread>iterator;public SelectNextSelectorThread(Collectionthreads) {this.threads =threads;

iterator= this.threads.iterator();

}/*** 选择下一个SelectorThread,这里为轮询

*

*@returnSelectorThread*/

publicSelectorThread nextThread() {if (!iterator.hasNext()) {

iterator=threads.iterator();

}returniterator.next();

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值