2012-04-03 14 views
30

Ho creato un pezzo di codice che accetta un indirizzo IP (dal metodo principale in un'altra classe) e quindi esegue il ciclo di un intervallo di indirizzi IP eseguendo il ping di ognuno di essi mentre procede. Ho un front-end GUI su questo ed è andato in crash (quindi perché ho fatto il multithreading.Il mio problema è che non posso più prendere l'indirizzo IP come argomento nel mio codice ping come il suo callable. per questo e non riesco a trovare un modo per aggirare questo. C'è un modo per un metodo callable per prendere argomenti? Se non c'è un altro modo per realizzare ciò che sto cercando di fare?C'è un modo per prendere una discussione in un metodo callable?

campione del mio codice:.

public class doPing implements Callable<String>{ 

public String call() throws Exception{ 

    String pingOutput = null; 

    //gets IP address and places into new IP object 
    InetAddress IPAddress = InetAddress.getByName(IPtoPing); 
    //finds if IP is reachable or not. a timeout timer of 3000 milliseconds is set. 
    //Results can vary depending on permissions so cmd method of doing this has also been added as backup 
    boolean reachable = IPAddress.isReachable(1400); 

    if (reachable){ 
      pingOutput = IPtoPing + " is reachable.\n"; 
    }else{ 
     //runs ping command once on the IP address in CMD 
     Process ping = Runtime.getRuntime().exec("ping " + IPtoPing + " -n 1 -w 300"); 
     //reads input from command line 
     BufferedReader in = new BufferedReader(new InputStreamReader(ping.getInputStream())); 
     String line; 
     int lineCount = 0; 
     while ((line = in.readLine()) != null) { 
      //increase line count to find part of command prompt output that we want 
      lineCount++; 
      //when line count is 3 print result 
      if (lineCount == 3){ 
       pingOutput = "Ping to " + IPtoPing + ": " + line + "\n"; 
      } 
     } 
    } 
    return pingOutput; 
} 
} 

IPtoPing usato per essere l'argomento che è stata presa

risposta

37

Non è possibile passare come argomento a call() perché la firma del metodo non lo consente.

Tuttavia, è possibile passarlo come argomento del costruttore; per esempio.

public class DoPing implements Callable<String>{ 
    private final String ipToPing; 

    public DoPing(String ipToPing) { 
     this.ipToPing = ipToPing; 
    } 

    public String call() throws SomeException { 
     InetAddress ipAddress = InetAddress.getByName(ipToPing); 
     .... 
    } 
} 

(ho corretto un paio di violazioni in stile codice eclatanti !!)

alternativa, è possibile:

  • dichiarare il doping come una classe interna e lo hanno riferimento a una final ipToPing nell'ambito di inclusione o

  • aggiungere un metodo setIpToPing(String ipToPing).

(L'ultimo permette un oggetto DoPing per essere riutilizzato, ma il lato negativo è che è necessario sincronizzare per accedervi thread-sicurezza.)

+0

così .... questo non funzionerà se si passa il Callable come parametro a un'altra funzione che cerca di iterare il Callable contro una serie di argomenti è stato passato ... – Michael

+0

È inteso come una dichiarazione o una domanda? Ad ogni modo, non riesco a capire cosa stai dicendo/chiedi. –

5

Quando si crea il doping classe (dovrebbe essere la lettera captial in nome della classe), inviare in th indirizzo ip nel costruttore. Usa questo indirizzo IP nel metodo di chiamata.

4

Metti un po '(final) Campi nella classe doPing, e un costruttore che li inizializza, quindi passare i valori che si desidera utilizzare in call() al costruttore di doPing:

public class doPing implements Callable<String> { 
    private final String ipToPing; 

    public doPing(String ip) { 
     this.ipToPing = ip; 
    } 

    public String call() { 
     // use ipToPing 
    } 
} 
6

Aggiungendo alla risposta di Jarle - nel caso in cui si crea Callable come istanza della classe anonima, è possibile utilizzare final campo al di fuori della classe anonima per il passaggio dei dati nell'istanza:

final int arg = 64; 
    executor.submit(new Callable<Integer>() { 
     public Integer call() throws Exception { 
      return arg * 2; 
     } 
    }); 
1

Hai a defien una proprietà come ipAddress e la sua funzione di accesso incontrato hod. e passando il suo valore nel metodo constructor o tramite il metodo setter. Nella classe utilizza la proprietà ipAddress.

class DoPing/* In java all classes start with capital letter */implements Callable<String> 
{ 
    private String ipAddress; 

    public String getIpAddress() 
    { 
     return ipAddress; 
    } 

    public void setIpAddress(String ipAddress) 
    { 
     this.ipAddress = ipAddress; 
    } 

    /* 
    * Counstructor 
    */ 
    public DoPing(String ipAddress) 
    { 
     this.ipAddress = ipAddress; 
    } 

    @Override 
    public String call() throws Exception 
    { 
     // your logic 
    } 
} 
2

Non è possibile passare argomenti per call() perché la firma del metodo non lo consente, ma qui è almeno un modo per aggirare che

  1. definire una classe astratta che avvolge/attrezzi Callable e
  2. implementare un setter a "iniettare" un risultato in call()

definire una classe astratta:

import java.util.concurrent.Callable; 

public abstract class Callback<T> implements Callable<Void> { 
    T result; 

    void setResult (T result) { 
     this.result = result; 
    } 

    public abstract Void call(); 
} 

Definire il metodo che dovrebbe licenziare il callback:

public void iWillFireTheCallback (Callback callback) { 
    // You could also specify the signature like so: 
    // Callback<Type of result> callback 

    // make some information ("the result") 
    // available to the callback function: 
    callback.setResult("Some result"); 

    // fire the callback: 
    callback.call(); 
} 

Nel luogo in cui si desidera chiamare iWillFireTheCallback:

Definire la funzione di callback (anche possibile all'interno dei metodi):

class MyCallback extends Callback { 
    @Override 
    public Void call() { 
     // this is the actual callback function 

     // the result variable is available right away: 
     Log.d("Callback", "The result is: " + result); 

     return null; 
    } 
} 

e quindi chiamare iWillFireTheCallback passando nel callback:

iWillFireTheCallback(new MyCallback());