¿Hay una manera de tomar un argumento en un método callable?


He creado un fragmento de código que toma una dirección IP (del método principal en otra clase) y luego recorre un rango de direcciones IP haciendo ping a cada una a medida que avanza. Tengo una interfaz gráfica de usuario en este y se estaba estrellando (por lo tanto, por qué he hecho el multihilo. Mi problema es que ya no puedo tomar la dirección IP como un argumento en mi código ping como su llamable. He buscado esto por todas partes y parece que no puedo encontrar una manera de evitarlo. ¿Hay una manera para que un método llamable tome ¿discusiones? Si no, ¿hay alguna otra manera de lograr lo que estoy tratando de hacer?

Ejemplo de mi código:

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;
}
}

El IPtoPing solía ser el argumento que se tomaba.

Author: Steve, 2012-04-03

6 answers

No puede pasarlo como argumento a call() porque la firma del método no lo permite.

Sin embargo, puede pasarlo como un argumento constructor; por ejemplo,

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);
        ....
    }
}

(He corregido un par de atroces violaciones de estilo de código!!)

Alternativamente, usted podría:

  • Declare el dopaje como una clase interna y haga que se refiera a un final ipToPing en el ámbito de aplicación adjunto, o

  • Añadir un método setIpToPing(String ipToPing).

(El último permite que un objeto DoPing sea reutilizado, pero la desventaja es que tendrá que sincronizar para acceder a él hilo-de forma segura.)

 40
Author: Stephen C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-22 05:09:51

Añadiendo a la respuesta de Jarle {en caso de que cree Callable como instancia de clase anónima, puede usar el campo final fuera de la clase anónima para pasar datos a la instancia:

    final int arg = 64;
    executor.submit(new Callable<Integer>() {
        public Integer call() throws Exception {
            return arg * 2;
        }
    });
 6
Author: Victor Sorokin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-03 12:19:19

Cuando cree la clase doPing (debe ser una letra capcial en el nombre de la clase), envíe la dirección ip en el constructor. Utilice esta dirección ip en el método de llamada.

 5
Author: Jarle Hansen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-03 12:14:07

Ponga algunos campos (final) en su clase doPing, y un constructor que los inicialice, luego pase los valores que desea usar en call() al constructor de doPing:

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

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

     public String call() {
         // use ipToPing
     }
}
 3
Author: daveb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-03 12:17:54

No puede pasar argumentos a call() porque la firma del método no lo permite, pero aquí hay al menos una forma de evitarlo mediante

  1. definiendo una clase abstracta que envuelve/implementa Callable y
  2. implementando un setter para" inyectar " un resultado en call()

Definir una clase abstracta:

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 ();
}

Define el método que debería activar la devolución de llamada:

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();
}

En el lugar donde quieres llamar iWillFireTheCallback:

Definir la función de devolución de llamada (incluso posible dentro de los métodos):

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;
    }
}

Y luego llame a iWillFireTheCallback mientras pasa la devolución de llamada:

iWillFireTheCallback(new MyCallback());
 2
Author: Per,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-14 16:01:03

Tienes que defien una propiedad como ipAddress y su método de accessor. y pasando su valor en constructor o por el método setter. En la clase doPing use la propiedad 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
    }
}
 1
Author: Sam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-03 12:23:35