从未返回结果的调用中获取结果?

时间:2015-12-15 22:12:19

标签: java concurrency future callable futuretask

我正在使用调用结果的API,但不会返回结果本身。调用完成后,将调用一个包含结果的单独方法(侦听器)。这是我想要实现的一个例子:

public static void main (String[] args) {
    Object obj = someMethod();

    System.out.println("The object is" + obj + ", wooh!");
}

public void callObject() {
    // This is the call that sends a request for the object
}

public void receiveObject(Object object) {
    // This is the API method that is invoked with the result (cannot be changed)
}

// What I want to be able to do
public Object someMethod() {
    callObject();
    // return received object once received, but how?
}

callObject()不返回对象,只启动对它的检索。我想有一个方法来调用对象,然后在收到它时返回它。我一直在研究Callables和Future的结果,但我不确定如何实现它们。

有什么想法吗?谢谢!

3 个答案:

答案 0 :(得分:0)

这个怎么样?在课堂上引入一个新领域:

private Object result;

然后在receiveObject(Object object)方法中设置它:

this.result = object;

在someMethod()中:

callObject();
while(this.result==null) {
    Thread.sleep(100);
}
Object answer = this.result;
this.result = null;
return answer;

只要为每个API请求创建此类的新实例,该工作正常。不要试图让这个班级成为一个单身人士,它只会让事情变得不必要地复杂化。

如果你真的需要一个单身人士,你可以将private Object result;概括为一个地图,并想出一种方法来识别每个单独的API调用,就像一些来电者ID一样。

最后,您还可以将private Object result;替换为java.util.concurrent.CompletableFuture。然后在receiveObject方法中完成该未来,并在.get()中等待它(someMethod)。这比使用线程睡眠循环更加惯用。

答案 1 :(得分:0)

最简单的情况:您以普通的阻止方式发送请求,并希望能够在主线程执行时执行某些操作。为此,请使用ExecutorService,通常是通过调用Executors创建的,例如:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class ToyConc1 {
    public static void main(String[] args) throws InterruptedException,
            ExecutionException {
        ExecutorService exec = Executors.newCachedThreadPool();
        try {
            Callable<String> op1 = new Callable<String>() {
                @Override
                public String call() throws Exception {
                    return slowlyGetHttpPage("http://www.google.com");
                }
            }; 
            Callable<String> op2 = new Callable<String>() {
                @Override
                public String call() throws Exception {
                    return slowlyGetHttpPage("http://edition.cnn.com/");
                }
            }; 
            Future<String> resF1 = exec.submit(op1);
            Future<String> resF2 = exec.submit(op2);

            for (int i = 0; i < 20; i++) {
                System.out.println("doing useful work on the main thread...");
            }
            System.out.println("The object 1 is " + limit(resF1.get(), 1000) + ", wooh!");
            System.out.println("The object 2 is " + limit(resF2.get(), 1000) + ", wooh!");
        } finally {
            exec.shutdown();
            exec.awaitTermination(60, TimeUnit.SECONDS);
        }
    }

    private static String slowlyGetHttpPage(String urlName) throws InterruptedException,
            IOException {
        Thread.sleep(2000);
        URL url = new URL(urlName);
        URLConnection conn = url.openConnection();
        InputStream in = conn.getInputStream();
        InputStreamReader reader = new InputStreamReader(in); // wrong charset maybe
        BufferedReader br = new BufferedReader(reader);
        StringBuilder sb = new StringBuilder();
        try {
            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            return sb.toString();
        } finally {
            br.close();
        }
    }

    private static String limit(String s, int length) {
        if (s == null) {
            return null;
        }
        if (s.length() <= length) {
            return s;
        }
        return s.substring(0, length) + " [and " + (s.length() - length) + " more]";
    }
}

或者,用于发送请求并返回结果的库/框架/技术可能已经为您提供类似Future的内容或接受类似回调的内容(例如AsyncHttpClient同时执行)

答案 2 :(得分:-1)

如何返回无法返回的内容,someMethod() return字在哪里,callObject()什么都不返回,因为它是{{1} }。这样它就会返回一个对象

void