-
见下面代码的:Thread.sleep(400000)部分,这里暂停线程模拟耗时操作后,别的客户端就连接不上了
- 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);
- }
- }
- }
- }
问题补充:wangqj 写道好比去肯德基吃饭,前台只有一个点餐员,如果客人要的餐简单,能快速的完成点餐(相当于IO处理),然后让客人等厨师做好饭(相当于后台业务处理),然后通知客人取餐。 这个时候能快速接受排队的客人的请求。 如果某个客人要了很多吃的,点餐的时间就比较长,后面排队的客人就要等,这时效率就低了
那这样的话业务逻辑处理部分(厨师做饭)就必须用线程(池)来做了,没办法2012年3月12日 17:06
2个答案按时间排序按投票排序
-
采纳的答案
获取连接,分发处理,获取key这个是主线程,但是后续处理应该另起线程,handler应该是新起的线程处理,例如这样:
- while (true)
- {
- selector.select();
- Set<SelectionKey> 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;
- }
- }
- }
- }
2012年3月12日 17:42
-
好比去肯德基吃饭,前台只有一个点餐员,如果客人要的餐简单,能快速的完成点餐(相当于IO处理),然后让客人等厨师做好饭(相当于后台业务处理),然后通知客人取餐。 这个时候能快速接受排队的客人的请求。 如果某个客人要了很多吃的,点餐的时间就比较长,后面排队的客人就要等,这时效率就低了