Is there a way to take an argument in a callable method?

后端 未结 7 1073
Happy的楠姐
Happy的楠姐 2020-12-23 16:41

I have created a piece of code which takes an IP address (from main method in another class) and then loops through a range of IP addresses pinging each one as it goes. I ha

7条回答
  •  佛祖请我去吃肉
    2020-12-23 17:01

    It is not always possible to make reference to (effectively) final variable to use its value as "argument", but you can make comfy general solution by yourself. First define this functional interface:

    @FunctionalInteface
    interface CallableFunction {
    
        public abstract R call(T arg) throws Exception;
    
        public static  Callable callable(CallableFunction cf, T arg) {
            return () -> cf.call(arg);
        }
    }
    

    This functional interface provides static method callable that creates a Callable instance, which simply calls call(T) with provided argument (of type T). Then you need you DoPing class to implement CallableFunction like this:

    public class DoPing implements CallableFunction {
    
        @Override
        public String call(final String ipToPing) throws Exception {
            final var ipAddress = InetAddress.getByName(ipToPing);
            final var reachable = ipAddress.isReachable(1400);
            String pingOutput = null;
            if (reachable) {
                pingOutput = ipToPing + " is reachable.\n";
            }
            else {
                final var ping = Runtime.getRuntime().exec("ping " + ipToPing + " -n 1 -w 300");
                try (var in = new BufferedReader(new InputStreamReader(ping.getInputStream()))) {
                    String line;
                    for (int lineCount = 1; (line = in.readLine()) != null; ++lineCount) {
                        if (lineCount == 3) {
                            pingOutput = "Ping to " + ipToPing + ": " + line + "\n";
                            break;
                        }
                    }
                }
            }
            return pingOutput;
        }
    

    Here we changed call signature to accept String argument and also now it implements CallableFunction and not Callable as before. Other changes are minor, but it's worth mentioning, that we prevented resource leak with use of try-with-resource on BufferedReader and also break has been added to input collecting loop (change from while to for) to terminate as quickly, as possible.

    Now you can use the code e.g. like this:

        final var ping = CallableFunction.callable(new DoPing(), "127.0.0.1");
        final var task = new FutureTask<>(ping);
        new Thread(task).start();
        System.out.println(task.get(20, TimeUnit.SECONDS));
    

    You can also reuse CallableFunction in other cases, when you needed it.

提交回复
热议问题