在不使用多线程的情况下对多个IP地址执行Ping操作

时间:2018-07-11 14:59:40

标签: java

我正在开发一个用于ping IP地址并生成有关故障和Java中其他统计信息的报告的系统。为了ping通多个IP地址,我希望一次对所有IP地址执行ping操作。使用多线程似乎是不可能的,因为我只有一种方法可以将IP地址和文本区域显示为参数。我在for循环中有此方法,在每次循环中都分配了参数。

public Runnable runSystemCommand(String command ,JTextArea replyView ) throws FileNotFoundException, 
        IOException, ClassNotFoundException, SQLException, InterruptedException, ExecutionException {
    return new Runnable(){
        public void run(){
            PingDB db = new PingDB();
            try {
                db.openConnection();
            } catch (ClassNotFoundException ex) {
                Logger.getLogger(ping_IP.class.getName()).log(Level.SEVERE, null, ex);
            }
           try{
               address = InetAddress.getByName(ip);
               status = address.isReachable(100000);

               //for (String ipAddress : ips){
               if (status){
                   Timestamp timeIn = new Timestamp(System.currentTimeMillis());
                   replyView.setText(replyView.getText()+ System.getProperty("line.separator")
                           +"Server reached at "+ timeIn);

               }else{
                   Timestamp tOut = new Timestamp(System.currentTimeMillis());
                  replyView.setText(replyView.getText()+ System.getProperty("line.separator")+
                          "Server timed out at "+tOut);

               }
               try {
                   p = Runtime.getRuntime().exec(command);

                   }catch (IOException ex) {
                   Logger.getLogger(ping_IP.class.getName()).log(Level.SEVERE, null, ex);
               }

                Scanner S = new Scanner(p.getInputStream());
                while (S.hasNextLine()) {
                    final String newText = S.nextLine();

                    if (newText.startsWith("Reply from ")||newText.startsWith("64 bytes of data")){

                        pingCount++;
                        //String sttm = "Insert into pingstatus Values ("+pingCount+",);";
                    }else{

                        timeOuts++;

                    }
                    EventQueue.invokeLater(new Runnable(){
                        public void run() {
                           //System.out.println(newText);
                           replyView.setText(replyView.getText()
                                    + System.getProperty("line.separator")
                                    + newText);
                        }
                    });

                }

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

                               }
        }          
    };
}
Executor executor = Executors.newFixedThreadPool(1);


private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
    //jButton is used to initiate the ping
    EventQueue.invokeLater(new Runnable() {
        public void run(){ 
            try {
                if (ips.size() == 1){

                    newPing.executor.execute(newPing.runSystemCommand("ping "+ips.get(0)+" -t",inputArea)); 

                }else{
                  //this is where the method above is called.  

                    for (String ip : ips) {
                        System.out.println(ip);
                        MultiView newView = new MultiView();
                        newView.setTitle("Pinging "+ip);
                        newView.setVisible(true);

                       newPing.executor.execute(newPing.runSystemCommand("ping "+ ip+" -t",newView.mView));

                    }
                }    
            } catch (FileNotFoundException ex) {
                Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException | ClassNotFoundException | SQLException | InterruptedException | ExecutionException ex) {
                Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
   });
}                                        

谢谢

1 个答案:

答案 0 :(得分:2)

在我看来,您反对多线程的论点无效:

  1. 您的要求是一次ping所有IP地址,这只是“同时”的另一句话。
  2. InetAddress.isReachable()以及调用和解析外部命令的输出具有阻塞性
  3. 您的代码可以重构,因此多线程更易于实现

使用SwingWorkers将后台工作(查验)与更新GUI分开。其他优点是(see the tutorials):

  • 提供结果以调用线程
  • 取消,发现后台任务已完成还是被取消
  • 后台任务完成(see SwingWorker.done())后更新GUI
  • 中间结果以更新EDT(see SwingWorker.process(...))中的GUI
  • 后台任务可以定义触发事件的绑定属性,从而导致在EDT上调用事件处理方法

您当前的代码从不是EDT的线程更新组件,而该EDT违反了Swings并发规则,使用Swing作业程序,您几乎可以免费解决此问题(无需像某些情况下那样使用EventQueue.invokeLater(...)

最后的一些建议:

  • 您也可以在后台任务中使用执行程序和线程池
  • 重构您的代码库以使类具有单一职责(处理外部程序输出,ping等)
  • InetAddress.isReachable(...)是否使用外部ping实用程序完成了很多工作,值得删除吗?

      

    如果特权,典型的实现将使用ICMP ECHO REQUEST   可以获得,否则它将尝试建立TCP连接   在目标主机的端口7(回显)上。