我正在开发一个用于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);
}
}
});
}
谢谢
答案 0 :(得分:2)
在我看来,您反对多线程的论点无效:
使用SwingWorkers将后台工作(查验)与更新GUI分开。其他优点是(see the tutorials):
您当前的代码从不是EDT的线程更新组件,而该EDT违反了Swings并发规则,使用Swing作业程序,您几乎可以免费解决此问题(无需像某些情况下那样使用EventQueue.invokeLater(...)
。
最后的一些建议:
InetAddress.isReachable(...)
是否使用外部ping实用程序完成了很多工作,值得删除吗?
如果特权,典型的实现将使用ICMP ECHO REQUEST 可以获得,否则它将尝试建立TCP连接 在目标主机的端口7(回显)上。