使用java nio的selector做一个数据查询主机

转载 2006年06月01日 12:13:00

1.[讨论]使用java nio的selector做一个数据查询主机
Posted by: koji
Posted on: 2003-10-29 12:40

之前跟米花大大讨论过的东西,想说跟大家分享讨论一下
最底下有图
名字可能取的有点不太好

基本上我是为了学校的东西必须做p2p的集权式主机
负责管理节目表,p2p client都必须去跟这台主机要求数据
所以写这个程序测试
会使用selector的原因在于
不希望有太多thread产生,外加想试试看nio
所以我希望固定thread数去处理多个connection

当使用者要查询节目时,每个connection都只会做查询数据库的动作
遇到最大问题是
selector在等待connection发生动作时,是block住的
所以当他在等待的时候无法接受其它connection的regist

下面这是javadoc的说明
--
A thread blocked in one of the select() or select(long) methods may be interrupted by some other thread in one of three ways:

*

By invoking the selector's wakeup method,
*

By invoking the selector's close method, or
*

By invoking the blocked thread's interrupt method, in which case its interrupt status will be set and the selector's wakeup method will be invoked.
--
所以后来就跟米花兄请教
最后就使用queue去塞要regist的connection

底下是我的code
不知这种设计方式怎样
请多多指教~

ServerWindow
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
public class ServerWindow
{
 static Logger log;
 public static int PORT_NUM = 28888;
 public WorkLine wline;
 
 static
 {
    log = Logger.getLogger(p2p.server.ServerWindow.class);
 }
    public ServerWindow()
    {
    }
 
   public static void main(String args[])
        throws Exception
    {
        (new ServerWindow()).go();
    }
 
    public void go()
        throws Exception
    {
        wline = new WorkLine();
        int i = PORT_NUM;
        log.info("Server is Listening on port: " + i);
        ServerSocketChannel serversocketchannel = ServerSocketChannel.open();
        ServerSocket serversocket = serversocketchannel.socket();
        serversocket.bind(new InetSocketAddress(i));
        serversocketchannel.configureBlocking(false);
        Selector selector = Selector.open();
        serversocketchannel.register(selector, SelectionKey.OP_ACCEPT);
        try
        {
      while(true)
            {
                int n = selector.select();
                if(n == 0)
                {
                  continue;
                }
                Iterator iterator = selector.selectedKeys().iterator();
                while(iterator.hasNext())
                {
                    SelectionKey selectionkey = (SelectionKey)iterator.next();
                    if(selectionkey.isAcceptable())
                    {
                        ServerSocketChannel serversocketchannel1 = (ServerSocketChannel)selectionkey.channel();
                        java.nio.channels.SocketChannel socketchannel = serversocketchannel1.accept();
                        wline.enQueue(socketchannel);
                    }
                    if(selectionkey.isReadable())
                    {
                        log.info("wont happened!!");
                    }
          iterator.remove();
                }
            }
        }
        catch(IOException ioexception)
        {
            log.error(ioexception);
            return;
        }
    }
}


WorkerThread
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
public class WorkerThread extends Thread implements Comparable, Serializable{
 
 static Logger log = Logger.getLogger(p2p.server.WorkerThread.class);
 private WorkLine wline;
 private Selector selector;
 private boolean READY;
 
 public WorkerThread(String name, WorkLine wline){
    try{
      this.setName(name);
     this.setWorkLine(wline);
      this.setReady(false);
      selector = Selector.open();
    }catch(Exception e){
      log.error(e);
    }
 }
 
 public void setReady( boolean ready ){
    this.READY = ready;
 }
 
 public void setWorkLine(WorkLine wline){
    this.wline = wline;
 }
 
 public void registChannel( ) throws Exception{
    this.setReady(true);
    selector.wakeup();
 }
 
 public int getSize(){
   
    return selector.keys().size();
   
 }
 
 public boolean equals(Object o){
   return false;
 }
 
 public void run(){
   
    Iterator iterator;
    SelectableChannel channel;
    try{
      while( true )
      { 
       
        if(READY == true){
          channel = (SelectableChannel)wline.getQueue().remove();
          if(channel != null){
            channel.configureBlocking(false);
            channel.register(selector, SelectionKey.OP_READ);
          }else{
            log.info("Wont happened!! channel is null");
            //System.out.println("Wont happened!!");
         }
        }
        READY = false;
       
        int n = selector.select();
        if( n == 0){
          continue;
        }
        Iterator it = selector.selectedKeys().iterator();
        while( it.hasNext() )
        {
     
          SelectionKey key = (SelectionKey) it.next();
          it.remove();
       
       
          if( key.isAcceptable() ){
            //wont happened 
            System.out.println("wont happened");
            log.info("wont happened!! channels are all ReadOPS ");
          }
          if(key.isReadable()){
            //receive search command
            log.info("Got the message!! Server is working!!");
            readDataFromSocket(key);
          }
          key = null;
        }
        }
      }
      
      catch(Exception e){
        log.error(e);
      } 
 }
 protected void readDataFromSocket(SelectionKey key) throws Exception
 {
    ByteBuffer buffer = ByteBuffer.allocate(100);
    try{
      SocketChannel socketChannel = (SocketChannel) key.channel( );
      ((SocketChannel)key.channel()).socket().setKeepAlive(true);
      int count;
      buffer.clear( ); // Empty buffer
      //Loop while data is available; channel is nonblocking
      while ((count = socketChannel.read (buffer)) > 0) {
        buffer.flip( ); // Make buffer readable
        while (buffer.hasRemaining( )) {
          Charset charset = Charset.forName("ISO-8859-1");
          CharsetDecoder decoder = charset.newDecoder();
          CharBuffer charBuffer = decoder.decode(buffer);
          //System.out.println( charBuffer.toString() );
          log.info( "Message-->" + charBuffer.toString() );
        }
      }
   
      if((count = socketChannel.read (buffer)) < 0){
        key.cancel();
        key.channel().close();
        log.info("connection closed naturally!!");
        //System.out.println("connection closed nature!!");
      }
    }catch(Exception e){
      log.info("connection closed immediately!!");
      //System.out.println("connection closed!!");
      key.cancel();
      key.channel().close();
    }finally{
      buffer.clear( );
    }
 }
 
 public int compareTo(Object o){
    WorkerThread temp =(WorkerThread)o;
    if(this.getSize() > temp.getSize())
      return 1;
    else if(this.getSize() < temp.getSize()){
      return -1;
    }else{
      return 1;
    }
 }
 
 public WorkLine getWorkLine() {
    return wline;
 }
 
}


ChannelQueue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class ChannelQueue
{
 private LinkedList list;
 
 public ChannelQueue()
 {
    list = new LinkedList();
 }
 
 public synchronized void add(Object obj)
 {
    list.add(obj);
 }
 
 public synchronized int size()
 {
    return list.size();
 }
 
 public synchronized Object remove()
 {
    Object obj = list.removeFirst();
    if(obj != null)
      return obj;
    else
      return null;
 }
 
 
}


WorkLine
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class WorkLine
{
 
 List set;
 ChannelQueue queue;
 
    public WorkLine()
    {
        set = new ArrayList();
        queue = new ChannelQueue();
        for(int i = 0; i < 10; i++)
        {
      WorkerThread worker = new WorkerThread("Thread:" + i, this);
            worker.start();
      set.add(worker);
        }
 
    }
 
    public void enQueue(Object obj)
        throws Exception
    {
        Collections.sort(set);
        queue.add(obj);
        ((WorkerThread)set.get(0)).registChannel();
    }
 
    public ChannelQueue getQueue()
    {
        return queue;
    }
 
}


2.Re:[讨论]使用java nio的selector做一个数据查询主机 [Re: koji]
Posted by: linexpmail
Posted on: 2003-10-29 15:13

推荐 NIO 的反应器样式,可以实作来比较看看:

http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf

分配责任清楚,过去实做过单执行绪版本,效能不错。

个人觉得反应器样式难在观察何时踩煞车,建议将
socketChannel.read (buffer) > 0 抽出实作
boolean inputIsComplete() { /* ... */ } 会比较清楚
责任所在。

实际上不同平台底层实作不同,有的环境会传回读取到 0
byte 的情形,抽出个 method 也好观察测试。

实做测试发现效能瓶颈是 CharsetDecoder,改成直接读 byte
会让你的反应器更猛。除非瓶颈已到,建议还是先实作单执行绪,
让反应器好好跑一跑看看。

3.Re:[讨论]使用java nio的selector做一个数据查询主机 [Re: koji]
Posted by: koji
Posted on: 2003-10-30 13:49

hmm
因为我是预设希望有几百个到千个联机
会去使用主机搜寻节目表
所以用单执行绪怕会让反应时间过长
多执行绪的话想说可以稍微平均一下反应时间

CharsetDecoder自己没测试过效能,感谢

用boolean inputIsComplete() { /* ... */ }会比较清楚
但是就像你给的pdf一样会变成我要把处理数据整个拉出来做对巴
下次改版看看

koji
 

Java NIO之Selector的使用

看了下关于Selector的使用方法,官方的说法是一个“多路复用器”,从我自己的角度来讲就感觉像一个服务总线,负责统一各个处理程序的消息注册,统一接收客户端或服务器消息信息,再分发给不同的事件处理程序...
  • zmx729618
  • zmx729618
  • 2016年07月08日 11:10
  • 2344

JAVA NIO的selector的实现原理

Java NIO的核心类库多路复用器Selector就是基于epoll的多路复用技术实现的 相比select、poll系统调用,epoll有如下优点:1.支持一个进程打开的socket描述符(FD)...
  • donsonzhang
  • donsonzhang
  • 2015年06月24日 20:23
  • 6307

java NIO selector全面深入理解

java NIO selector全面深入理解
  • lw305080
  • lw305080
  • 2016年04月21日 11:13
  • 3203

【JAVA】【NIO】7、Java NIO Selector

selector是Java NIO的组件可以检查一个或多个NIO的channel,并且决定哪个channel是为读写准备好了。这种方式,单个线程可以管理多个channel,也就是多个网络连接。为什么使...
  • chiweitree
  • chiweitree
  • 2015年03月18日 17:27
  • 1479

java nio Selector的使用-服务器端

前些时候花了一些时间在研究java.nio的api使用机制,看了好久,也觉得不习惯它的使用方式和用法.毕竟自己对C语言了解太少,也不太了解C语言在网络编程上的用法。对这种底层下的编程太不习惯,还是应该...
  • z69183787
  • z69183787
  • 2014年04月14日 11:21
  • 1223

NIO解读之多路复用器Selector

Selector类的结构图如下所示: Selector是JDK的NIO中最重要的类之一,当我们通过Selector.open()方法打开一个多路复用器的时候实际上执行的open方法为 publ...
  • yzq234040228
  • yzq234040228
  • 2015年03月20日 16:26
  • 1981

Java NIO之多个Selector的实现

欢迎大家讨论,我也是接触时间不长,有问题欢迎大家指正。欢迎转载,转载请注明出处 楔子 最近在研究JAVA NIO的相关知识,发现网上多是三种类型的研究文章,一是单Reactor单Selecto...
  • jjzhk
  • jjzhk
  • 2014年09月26日 07:15
  • 15000

《Java 源码分析》:Java NIO 之 Selector(第二部分selector.select())

《Java 源码分析》:Java NIO 之 Selector(第二部分selector.select())上篇博文《Java 源码分析》:Java NIO 之 Selector(第一部分Select...
  • u010412719
  • u010412719
  • 2016年10月14日 21:39
  • 3227

Java NIO Selector详解(含多人聊天室实例)

一、Java NIO 的核心组件Java NIO的核心组件包括:Channel(通道),Buffer(缓冲区),Selector(选择器),其中Channel和Buffer比较好理解 简单来说 NI...
  • jeffleo
  • jeffleo
  • 2017年01月23日 21:38
  • 2213

《Java源码解析》之NIO的Selector机制(Part1:Selector.open())

Selector机制之Selector.open()函数的解析在NIO中我们一般都是Channel与Selector配合使用的,一般情况下使用的方法如下://打开Selector来处理channel ...
  • u010853261
  • u010853261
  • 2016年12月05日 13:29
  • 2277
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:使用java nio的selector做一个数据查询主机
举报原因:
原因补充:

(最多只允许输入30个字)