2012-03-08 66 views
3

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

下面的第I部分是我的源代码,显示了类TrapReceiver的内容。在这堂课中,倾听法是充分利用这个工作的地方。该类在我想在所提及的JTeaxtArea上显示消息的JFrame类中进行了插入。我将JTextArea对象的引用,SNMP代理URL和端口发送到类TrapReceiver的构造函数中,然后调用TrapReceiver对象的run方法以在JFrame实例以外的单独线程中启动执行。下面的第二部分展示了我如何在JFrame实例中实例化TrapReceiver类。

当我运行应用程序时,我注意到JFrame实例(即GUI)冻结,并且没有消息正在JFrame实例内的所谓JTeaxtArea上打印,实例化了下面第I部分中所示的类TrapRececeiver。

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

P.S .:我已经验证TrapReceiver工作正常,并且可以在没有GUI的情况下作为独立应用程序运行时将消息打印到标准输出,但由于某些可能的线程同步问题,它会以某种方式冻结。我试图运行TrapReceiver而不把它放到线程中,即使在这种情况下,GUI仍然冻结。

PART我

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 

PART II

在下面,我在一个线程中运行类的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() 

    } 

回答

5

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

+0

似乎我忘了删除它。我刚刚完成了它,但GUI仍然冻结。根据java教程(位于http://docs.oracle.com/javase/tutorial/uiswing/events/generalrules.html),“因为所有的绘图和事件监听方法都在同一个线程中执行,所以缓慢的事件 - 监听器方法可能会使程序看起来没有反应,并且重新绘制速度很慢,如果需要通过事件执行一些冗长的操作,可以通过启动另一个线程来完成。 这,我已经在做我的applcation,但我不明白为什么它不起作用。 – 2012-03-08 13:33:43

+2

嘿,我解决了这个问题。我发送线程对象java.awt.inVokeLater方法,但它看起来只有一个事件调度线程(根据我从Java教程读取)。所以,你的建议帮助忘记了在constrcutor中删除电话是我的错误。总之,上文第二部分的调用是正确的做法。谢谢。 – 2012-03-08 13:39:09

+1

对不起太多复制粘贴露出了我的头脑云,但如果有人需要上面的snmp陷阱是工作代码:) – 2012-03-08 13:40:09