posts - 28,  comments - 15,  trackbacks - 0

               本文主要利用nio包中的SocketChannel和Selector模擬實(shí)現(xiàn)ping命令(linux),下面的示例是Sun提供的,有助于理解SocketChannel與Selector的使用。對(duì)于初學(xué)者而言,有明白以下幾件事情:
              <1> 調(diào)用Selector.selector()方法將會(huì)導(dǎo)致當(dāng)前線程阻塞;
              <2> Selector阻塞后,以下事件將導(dǎo)致Selector活躍:
                          (1)其他線程或者當(dāng)前線程為通道向Selector中注冊(cè)了感興趣的事件(Connect、Accept、Read、Write);
                          (2)其他線程調(diào)用了selector的wakeup方法;


              明白了這些以下代碼對(duì)你來說,就是小菜一疊,以上是我看代碼的一點(diǎn)體會(huì),希望指正!

          public class Ping {
               
          // The default daytime port
              static int DAYTIME_PORT = 13;

              
          // The port we'll actually use
              static int port = DAYTIME_PORT;


              
          // Representation of a ping target
              
          // 
              static class Target {

                  InetSocketAddress address;
                  SocketChannel channel;
                  Exception failure;
                  
          long connectStart;
                  
          long connectFinish = 0;
                  
          boolean shown = false;

                  Target(String host) 
          {
                      
          try {
                      address 
          = new InetSocketAddress(InetAddress.getByName(host),
                                      port);
                      }
           catch (IOException x) {
                      failure 
          = x;
                      }

                  }

                  
          /*打印信息*/
                  
          void show() {
                      String result;
                      
          if (connectFinish != 0)
                          result 
          = Long.toString(connectFinish - connectStart) + "ms";
                      
          else if (failure != null)
                          result 
          = failure.toString();
                      
          else
                          result 
          = "Timed out";
                      
                      System.out.println(address 
          + " : " + result);
                      shown 
          = true;
                  }


              }



              
          // Thread for printing targets as they're heard from
              
          //
              static class Printer extends Thread
              
          {
                  LinkedList pending 
          = new LinkedList();
              
                  Printer() 
          {
                      setName(
          "Printer");
                      setDaemon(
          true);
                  }


                  
          void add(Target t) {
                      
          synchronized (pending) {
                          pending.add(t);
                          pending.notify();
                      }

                  }


                  
          public void run() {
                      
          try {
                          
          for (;;) {
                              Target t 
          = null;
                              
          synchronized (pending) {
                                  
          while (pending.size() == 0)
                                      pending.wait();
                                  
          //喚醒后刪除target
                                  t = (Target)pending.removeFirst();
                              }

                              
                              t.show();
                          }

                      }
           catch (InterruptedException x) {
                          
          return;
                      }

                  }


              }



              
          // Thread for connecting to all targets in parallel via a single selector
              
          // 
              static class Connector extends Thread{
                  
                  Selector sel;
                  Printer printer;
              
                  
          // List of pending targets.  We use this list because if we try to
                  
          // register a channel with the selector while the connector thread is
                  
          // blocked in the selector then we will block.
                  
          //
                  LinkedList pending = new LinkedList();
              
                  Connector(Printer pr) 
          throws IOException {
                      printer 
          = pr;
                      sel 
          = Selector.open();
                      setName(
          "Connector");
                  }


                  
          // Initiate a connection sequence to the given target and add the
                  
          // target to the pending-target list
                  void add(Target t) {
                      SocketChannel sc 
          = null;
                      
          try {
              
                          
          // Open the channel, set it to non-blocking, initiate connect
                          
          //在收到添加一個(gè)target的請(qǐng)求時(shí),打開通道
                          sc = SocketChannel.open();
                          
          //把通道注冊(cè)為非阻塞的
                          sc.configureBlocking(false);
              
                          
          boolean connected = sc.connect(t.address);
                          System.out.println(
          "if connected:"+connected);
                          
          // Record the time we started
                          t.channel = sc;
                          t.connectStart 
          = System.currentTimeMillis();
              
                      
          if (connected) {
                          t.connectFinish 
          = t.connectStart;
                          sc.close();
                          printer.add(t);
                      }
           else {
                          
          // Add the new channel to the pending list
          //                synchronized (pending) {
          //                    pending.add(t);
          //                }
              
                          
          // Nudge the selector so that it will process the pending list
                          sel.wakeup();
                      }

                      }
           catch (IOException x) {
                          
          if (sc != null{
                              
          try {
                              sc.close();
                              }
           catch (IOException xx) { }
                          }

                          t.failure 
          = x;
                          printer.add(t);
                      }

                  }


                  
          // Process any targets in the pending list
                  
          //
                  void processPendingTargets() throws IOException {
                      
          synchronized (pending) {
                          
          while (pending.size() > 0{
                              Target t 
          = (Target)pending.removeFirst();
                              
          try {
                  
                              
          // Register the channel with the selector, indicating
                              
          // interest in connection completion and attaching the
                              
          // target object so that we can get the target back
                              
          // after the key is added to the selector's
                              
          // selected-key set
                              t.channel.register(sel, SelectionKey.OP_CONNECT, t);
                  
                              }
           catch (IOException x) {
                  
                                  
          // Something went wrong, so close the channel and
                                  
          // record the failure
                                  t.channel.close();
                                  t.failure 
          = x;
                                  printer.add(t);
                  
                              }

                  
                          }

                      }

                  }


              
          // Process keys that have become selected
              
          //
                  void processSelectedKeys() throws IOException {
                      
          for (Iterator i = sel.selectedKeys().iterator(); i.hasNext();) {
              
                      
          // Retrieve the next key and remove it from the set
                      SelectionKey sk = (SelectionKey)i.next();
                      i.remove();
              
                      
          // Retrieve the target and the channel
                      Target t = (Target)sk.attachment();
                      SocketChannel sc 
          = (SocketChannel)sk.channel();
              
                      
          // Attempt to complete the connection sequence
                      try {
                          
          if (sc.finishConnect()) {
                              sk.cancel();
                              t.connectFinish 
          = System.currentTimeMillis();
                              sc.close();
                              printer.add(t);
                          }

                      }
           catch (IOException x) {
                          sc.close();
                          t.failure 
          = x;
                          printer.add(t);
                      }

                      }

                  }


                  
          volatile boolean shutdown = false;

              
          // Invoked by the main thread when it's time to shut down
                  void shutdown() {
                      shutdown 
          = true;
                      sel.wakeup();
                  }


                  
          // connector線程執(zhí)行的過程描述
                  
          // 啟動(dòng)-->調(diào)用select()-->導(dǎo)致線程阻塞
                  
          //                  -->add()方法調(diào)用selecor.wakeup激活阻塞-->n=0-->執(zhí)行注冊(cè)感興趣的事件-->select()-->n=1-->處理target連接-->select()-->線程阻塞
                  
          //                         -->main函數(shù)中的sleep過后,調(diào)用shutdown()方法,shutdown()中調(diào)用selector.wakeup(),喚醒線程,線程執(zhí)行完成。  
                  public void run() {
                      
          for (;;) {
                          
          try {
                              
          int n = sel.select();//這里需要注意:線程啟動(dòng)后,select方法的執(zhí)行將會(huì)導(dǎo)致線程阻塞,直到有感興趣的事件或者selector.wakeup()調(diào)用激活。
                              if (n > 0)processSelectedKeys();//由于通道沒有注冊(cè)感興趣事件,即使是selector.wakeup()激活阻塞,這里的n也等于0
                             
                              processPendingTargets();
                              
                              
          if (shutdown) {
                                  sel.close();
                                  
          return;
                              }

                          }
           catch (IOException x) {
                              x.printStackTrace();
                          }

                      }

                  }


              }



              
          public static void main(String[] args)throws InterruptedException, IOException{
              
          //        if (args.length < 1) {
          //            System.err.println("Usage: java Ping [port] host");
          //            return;
          //        }
          //        
                  int firstArg = 1;
          //    
          //        // If the first argument is a string of digits then we take that
          //        // to be the port number to use
          //        if (Pattern.matches("[0-9]+", args[0])) {
          //            port = Integer.parseInt(args[0]);
          //            firstArg = 1;
          //        }
              
                  port 
          = new Integer(80);
                  
          // Create the threads and start them up
                  Printer printer = new Printer();
                  printer.start();
                  Connector connector 
          = new Connector(printer);
                  connector.start();
              
                  
          // Create the targets and add them to the connector
                  LinkedList targets = new LinkedList();
                  
          for (int i = firstArg; i < 2; i++{
                      Target t 
          = new Target("localhost");
                      targets.add(t);
                      connector.add(t);
                  }

              
                  
          //等待指定的時(shí)間關(guān)閉connector線程
                  Thread.sleep(50000);
                  connector.shutdown();
          //設(shè)置connector線程關(guān)閉標(biāo)識(shí)位,同時(shí)喚醒阻塞的selector
                  
          //阻塞當(dāng)前調(diào)用線程,等待connector線程執(zhí)行完畢(join的經(jīng)典用法)
                  connector.join();
              
                  
          // Print status of targets that have not yet been shown
                  for (Iterator i = targets.iterator(); i.hasNext();) {
                      Target t 
          = (Target)i.next();
                      
          if (!t.shown)
                          t.show();
                  }


              }


          打印結(jié)果:

          /10.10.10.153:80 : 50024ms


          posted on 2012-02-07 16:53 zhangxl 閱讀(916) 評(píng)論(0)  編輯  收藏 所屬分類: java concurrency

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          <2012年2月>
          2930311234
          567891011
          12131415161718
          19202122232425
          26272829123
          45678910

          常用鏈接

          留言簿(1)

          隨筆分類(17)

          隨筆檔案(28)

          文章分類(30)

          文章檔案(30)

          相冊(cè)

          收藏夾(2)

          hibernate

          java基礎(chǔ)

          mysql

          xml

          關(guān)注

          壓力測(cè)試

          算法

          最新隨筆

          搜索

          •  

          積分與排名

          • 積分 - 96363
          • 排名 - 601

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 盐源县| 阿合奇县| 海门市| 嘉禾县| 莫力| 财经| 屏东市| 新疆| 墨玉县| 铜山县| 北宁市| 曲周县| 张家口市| 达日县| 武冈市| 凤阳县| 肃南| 开平市| 大同县| 浏阳市| 隆林| 鄱阳县| 牟定县| 金门县| 堆龙德庆县| 万全县| 盖州市| 长丰县| 舞阳县| 个旧市| 绥江县| 射洪县| 凯里市| 安仁县| 芦溪县| 南开区| 遵化市| 阿拉尔市| 长沙市| 鸡西市| 饶阳县|