使用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 IO模型&NIO

Java IO模型&NIO Java IO模型NIO 楔子 概述 网络服务 经典的服务设计 经典的SocketServer循环阻塞 可伸缩目标 分而治之 事件驱动设计 背景知识AWT 事件 React...

Java NIO服务器:远程主机强迫关闭了一个现有的连接

Java NIO聊天室 中,若客户端强制关闭,服务器会报“java.io.IOException: 远程主机强迫关闭了一个现有的连接。”,并且服务器会在报错后停止运行,错误的意思就是客户端关闭了,但是...

java nio Selector的使用-客户端

博客分类: java nio Javalog4j工作   接上一篇,客户端的程序就相对于简单了,只需要负责连接,发送下载文件名,再读数据就行了。主要步骤就是注册->连接服务器->发送下载请求...

Java NIO之Selector的使用

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

Java Nio selector例程

  • 2016-06-13 18:39
  • 1.71MB
  • 下载

java nio Selector的使用-服务器端

Java编程SocketCC++   前些时候花了一些时间在研究java.nio的api使用机制,看了好久,也觉得不习惯它的使用方式和用法.毕竟自己对C语言了解太少,也不太了解C语言在网络编...

网卡驱动4-做一个与外界交互的虚拟网卡3(调用真实网卡接收数据以及napi使用)

//vnic_rcv是接受vnic包的处理函数 static int vnic_rcv(struct sk_buff *skb, structnet_device *dev, struct pack...

java入门:java学习、java路线图、java教程丨如何做一个成功的大数据项目

今天主要分享六方面的内容:1、失败大数据项目的特征;2、成功大数据项目的选择;3、成功大数据项目的目标;4、成功大数据项目的衡量标准;5、成功大数据项目的路线图;6、成功大数据项目实战案例

使用Java做一个山寨的IE浏览器

/** 使用Java编写一个山寨的IE浏览器 能够向浏览器一样获得信息 浏览器也就是一个TCP客户端 不过想要向网络上的主机请求信息时必须按照一定的 格式发送请求信息。 然后再接收返回的信息,并把它...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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