wuqiangnimei 2012-03-12 17:06
浏览 213
已采纳

关于NIO的疑问,NIO是单线程的,如果后台有比较耗时的操作,别的客户端不就连不进来了?

见下面代码的:Thread.sleep(400000)部分,这里暂停线程模拟耗时操作后,别的客户端就连接不上了
[code="java"]
import java.io.IOException;

import java.net.InetSocketAddress;

import java.net.ServerSocket;

import java.nio.ByteBuffer;

import java.nio.channels.ClosedChannelException;

import java.nio.channels.SelectionKey;

import java.nio.channels.Selector;

import java.nio.channels.ServerSocketChannel;

import java.nio.channels.SocketChannel;

import java.util.Iterator;

/** 
 * @author marlonyao<yaolei135@gmail.com> 
 * 
 */  
public class EchoServer3 {  
    public static int DEFAULT_PORT = 9898;  

    interface Handler {  
        void execute(Selector selector, SelectionKey key);  
    }  


    public static void main(String[] args) throws IOException {  
        System.out.println("Listening for connection on port " + DEFAULT_PORT);  

        Selector selector = Selector.open();  
        initServer(selector);  

        while (true) {  
            selector.select();  

            for (Iterator<SelectionKey> itor = selector.selectedKeys().iterator(); itor.hasNext();) {  
                SelectionKey key = (SelectionKey) itor.next();  
                itor.remove();  
                Handler handler = (Handler) key.attachment();  
                handler.execute(selector, key);  
            }  
        }  
    }  

    private static void initServer(Selector selector) throws IOException,  
            ClosedChannelException {  
        ServerSocketChannel serverChannel = ServerSocketChannel.open();  
        ServerSocket ss = serverChannel.socket();  
        ss.bind(new InetSocketAddress(DEFAULT_PORT));  
        serverChannel.configureBlocking(false);  
        SelectionKey serverKey = serverChannel.register(selector, SelectionKey.OP_ACCEPT);  
        serverKey.attach(new ServerHandler());  
    }  

    static class ServerHandler implements Handler {  
        public void execute(Selector selector, SelectionKey key) {  
            ServerSocketChannel server = (ServerSocketChannel) key.channel();  
            SocketChannel client = null;  
            try {  
                client = server.accept();  
                System.out.println("Accepted connection from " + client);  
            } catch (IOException e) {  
                e.printStackTrace();  
                return;  
            }  

            SelectionKey clientKey = null;  
            try {  
                client.configureBlocking(false);  
                clientKey = client.register(selector, SelectionKey.OP_READ);  
                clientKey.attach(new ClientHandler());  
            } catch (IOException e) {  
                if (clientKey != null)  
                    clientKey.cancel();  
                try { client.close(); } catch (IOException ioe) { }  
            }  
        }  
    }  

    static class ClientHandler implements Handler {  
        private ByteBuffer buffer;  

        public ClientHandler() {  
            buffer = ByteBuffer.allocate(100);  
        }  

        public void execute(Selector selector, SelectionKey key) {  
            try {  
                if (key.isReadable()) {  
                    readKey(selector, key);  
                } else if (key.isWritable()) {  
                    writeKey(selector, key);  
                }  
            } catch (IOException e) {  
                key.cancel();  
                try { key.channel().close(); } catch (IOException ioe) { }  
            }  
        }  

        private void readKey(Selector selector, SelectionKey key) throws IOException {  
            SocketChannel client = (SocketChannel) key.channel();  
            try {  
                Thread.sleep(400000); 
            } catch (InterruptedException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
            int n = client.read(buffer);  
            if (n > 0) {  
                buffer.flip();  
                key.interestOps(SelectionKey.OP_WRITE);     // switch to OP_WRITE  
            }  
        }  

        private void writeKey(Selector selector, SelectionKey key) throws IOException {  
            System.out.println("is writable...");  
            SocketChannel client = (SocketChannel) key.channel();  
            client.write(buffer);  
            if (buffer.remaining() == 0) {  // write finished, switch to OP_READ  
                buffer.clear();  
                key.interestOps(SelectionKey.OP_READ);  
            }  
        }  
    }  
}  

[/code]

  • 写回答

2条回答 默认 最新

  • Aronlulu 2012-03-12 17:42
    关注

    获取连接,分发处理,获取key这个是主线程,但是后续处理应该另起线程,handler应该是新起的线程处理,例如这样:
    [code="java"]
    while (true)
    {
    selector.select();
    Set keys = selector.selectedKeys();
    for (SelectionKey key : keys)
    {
    if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT)
    {
    ServerSocketChannel ss = (ServerSocketChannel) key
    .channel();
    SocketChannel sc = ss.accept();
    sc.configureBlocking(false);
    sc.register(selector, SelectionKey.OP_READ);
    keys.remove(key);
    }
    if ((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ)
    {
    SocketChannel cc = (SocketChannel) key.channel();
    if (ReadThread.tag)
    {
    ReadThread readThread = new ReadThread();
    readThread.setChannel(cc);
    readThread.start();
    keys.remove(key);
    ReadThread.tag = false;
    }
    }

                }
    
            }
    

    [/code]

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 maple软件,用solve求反函数出现rootof,怎么办?
  • ¥50 汇编语言除法溢出问题
  • ¥15 Visual Studio问题
  • ¥15 state显示变量是字符串形式,但是仍然红色,无法引用,并显示类型不匹配
  • ¥20 求一个html代码,有偿
  • ¥100 关于使用MATLAB中copularnd函数的问题
  • ¥20 在虚拟机的pycharm上
  • ¥15 jupyterthemes 设置完毕后没有效果
  • ¥15 matlab图像高斯低通滤波
  • ¥15 针对曲面部件的制孔路径规划,大家有什么思路吗