【问题标题】:Java SNMP4J Trap application is freezing the GUIJava SNMP4J Trap 应用程序正在冻结 GUI
【发布时间】:2012-03-08 13:03:53
【问题描述】:

我有一个 Java 中的 SNMP 陷阱应用程序,旨在侦听 SNMP 代理并在 JFrame 窗口中的 JTextArea 上打印收到的 SNMP 消息。

下面的第一部分是我的源代码,显示了类 TrapReceiver 的内容。在这个类中,listen 方法是最能发挥作用的地方。该类在一个 JFrame 类中被实例化,我打算在上面提到的 JTeaxtArea 上显示消息。我将 JTextArea 对象的引用、SNMP 代理 URL 和端口发送到类 TrapReceiver 的构造函数中,然后调用 TrapReceiver 对象的 run 方法以在 JFrame 实例之外的单独线程中开始执行。下面的第二部分展示了我如何在 JFrame 实例中实例化类 TrapReeceiver。

当我运行应用程序时,我注意到 JFrame 实例(即 GUI)正在冻结,并且在 JFrame 实例中提到的 JTeaxtArea 上没有打印任何消息,该实例实例化了下面第一部分中显示的类 TrapReeceiver。

我的问题是尽管 TRapReceiver 本身作为单独的线程执行,但为什么 JFrame 实例(即 GUI)会冻结?另外,我想知道这个冻结问题的可能解决方案是什么。提前致谢。

第一部分

 package com.[Intenionally removed].snmp;

 import java.io.IOException;
 import javax.swing.JTextArea;
 import org.snmp4j.*;
 import org.snmp4j.mp.MPv1;
 import org.snmp4j.mp.MPv2c;
 import org.snmp4j.security.Priv3DES;
 import org.snmp4j.security.SecurityProtocols;
 import org.snmp4j.smi.OctetString;
 import org.snmp4j.smi.TcpAddress;
 import org.snmp4j.smi.TransportIpAddress;
 import org.snmp4j.smi.UdpAddress;
 import org.snmp4j.transport.AbstractTransportMapping;
 import org.snmp4j.transport.DefaultTcpTransportMapping;
 import org.snmp4j.transport.DefaultUdpTransportMapping;
 import org.snmp4j.util.MultiThreadedMessageDispatcher;
 import org.snmp4j.util.ThreadPool;

 public class TrapReceiver implements CommandResponder, Runnable {

   private String targetSnmpAgentURL;
   private int targetSnmpAgentPort;
   private JTextArea outConsole;

   public TrapReceiver() {
   } 

   public TrapReceiver(JTextArea outConsole) {
       this.outConsole = outConsole;
   }


   public TrapReceiver(JTextArea outConsole, String targetSnmpAgentURL, int  targetSnmpAgentPort) {
       this.targetSnmpAgentURL = targetSnmpAgentURL;
       this.targetSnmpAgentPort = targetSnmpAgentPort;
       this.outConsole = outConsole;

       try {
           listen(new UdpAddress(targetSnmpAgentURL + "/" + targetSnmpAgentPort));
       } catch (IOException e) {
           e.printStackTrace();
       }
    }

    public final synchronized void listen(TransportIpAddress address) throws IOException {


        AbstractTransportMapping transport;
        if (address instanceof TcpAddress) {
            transport = new DefaultTcpTransportMapping((TcpAddress) address);
        } else {
            transport = new DefaultUdpTransportMapping((UdpAddress) address);
        }

        ThreadPool threadPool = ThreadPool.create("DispatcherPool", 10);
        MessageDispatcher mDispathcher = new MultiThreadedMessageDispatcher(
            threadPool, new MessageDispatcherImpl());

        // add message processing models
        mDispathcher.addMessageProcessingModel(new MPv1());
       mDispathcher.addMessageProcessingModel(new MPv2c());

        // add all security protocols
        SecurityProtocols.getInstance().addDefaultProtocols();
        SecurityProtocols.getInstance().addPrivacyProtocol(new Priv3DES());

        // Create Target
        CommunityTarget target = new CommunityTarget();
        target.setCommunity(new OctetString("public"));

        Snmp snmp = new Snmp(mDispathcher, transport);
        snmp.addCommandResponder(this);

        transport.listen();
        System.out.println("Listening on " + address);

        try {
           this.wait();
        } catch (InterruptedException ex) {
           Thread.currentThread().interrupt();
        }
        }

    /**
    * This method will be called whenever a pdu is received on the given port
    * specified in the listen() method
    */
    @Override
    public synchronized void processPdu(CommandResponderEvent cmdRespEvent) {
        //System.out.println("Received PDU...");
        outConsole.append("Received PDU...\n");
        PDU pdu = cmdRespEvent.getPDU();

        if (pdu != null) {            
        outConsole.append("Trap Type = " + pdu.getType() + "\n");
        outConsole.append("Alarm Type: " + pdu.getVariableBindings().get(4) + "\n");
        outConsole.append("Alarm Message:  " + pdu.getVariableBindings().get(9) +  "\n\n");

        }
     }


     @Override
     public void run() {
        try {           
            listen(new UdpAddress(targetSnmpAgentURL + "/" + targetSnmpAgentPort));
        } catch (IOException e) {
            outConsole.append("\nError occured while listening to SNMP messages: \n" + e.getMessage() + "\n\n");
        }
     }

} //end of class TrapReceiver

第二部分

在下文中,我在线程中运行 TrapReceiver 类的实例。

   private void jButtonStartListeningSNMPActionPerformed(java.awt.event.ActionEvent evt)   {                                                          

    Thread snmpThread = 
           new Thread(new TrapReceiver(jTextAreaSNMPAlarmOutput, jTextFieldSnmpAgentUrl.getText().trim(), Integer.parseInt(jTextFieldSnmpAgentPort.getText().trim())));
    snmpThread.start()

   }

【问题讨论】:

    标签: java multithreading swing jframe snmp4j


    【解决方案1】:

    问题是您在TrapReceiver 构造函数中调用listen(),这发生在gui 线程上。您只想在run() 方法中调用listen(),因为这是在新线程中发生的部分。

    【讨论】:

    • 好像我忘了删除它。我刚刚完成了,但 GUI 仍然冻结。根据java教程(docs.oracle.com/javase/tutorial/uiswing/events/…),“因为所有的绘图和事件监听方法都在同一个线程中执行,一个缓慢的事件监听方法可能会使程序看起来没有响应并且重新绘制本身很慢。如果你需要作为事件的结果执行一些冗长的操作,通过启动另一个线程来完成“。这个,我已经在我的应用程序中做了,但我不明白为什么它不起作用。
    • 嘿,我解决了这个问题。我正在将线程对象发送到 java.awt.inVokeLater 方法,但看起来只能有一个事件调度线程(根据我从 Java 教程中读到的内容)。所以,你的建议帮助我忘记删除 constrcutor 中的调用是我的错误。总之,上面第 II 部分中的调用是正确的方法。谢谢。
    • 对不起,太多的复制粘贴让我的思绪浮现在云端,但如果有人需要上面的 snmp 陷阱,那就是工作代码:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-09
    • 2015-05-09
    • 2023-03-07
    • 2012-06-26
    • 1970-01-01
    相关资源
    最近更新 更多