2015-12-15 1 views
0

J'utilise une API qui appelle les résultats, mais ne renvoie pas le résultat lui-même. Une fois l'appel effectué, une méthode distincte (un écouteur) est appelée, qui contient le résultat. Voici un exemple de ce que je suis en train de réaliser:Obtenez le résultat d'un appel qui ne renvoie pas le résultat?

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

Le callObject() ne renvoie pas un objet, n'initie la récupération de celui-ci. Je veux avoir une méthode qui appelle l'objet, puis le renvoie quand il a été reçu. J'ai examiné les résultats de Callables et de Future, mais je ne suis pas sûr de savoir comment les mettre en œuvre.

Une idée? Merci!

+2

Votre question n'est pas claire. – Perdomoff

+2

Est-ce censé être non-bloquant? Une solution courante consiste à passer un objet [callback] (https://en.wikipedia.org/wiki/Callback_%28computer_programming%29) à la méthode 'callObject'. –

+0

@Perdomoff Je vais faire un montage, ours avec moi. – Anonomoose

Répondre

0

cas le plus simple: vous envoyez votre demande d'une manière de blocage ordinaire et que vous voulez être en mesure de faire quelque chose sur le thread principal alors qu'il est en cours d'exécution. Pour cela, utilisez ExecutorService, généralement créé par un appel à Executors, par exemple:

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

Sinon, la bibliothèque/framework/technique que vous utilisez pour envoyer la demande et renvoyer le résultat peut déjà vous donner quelque chose comme un Future ou accepter quelque chose comme un rappel (par exemple AsyncHttpClient fait les deux).

0

Que diriez-vous de ceci. Introduire un nouveau champ dans votre classe:

private Object result; 

Ensuite, dans le receiveObject (objet Object) Méthode vous le définissez:

this.result = object; 

En someMethod():

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

devrait fonctionner correctement , tant que vous créez une nouvelle instance de cette classe pour chaque requête d'API. N'essayez pas de faire de cette classe un singleton, ça va rendre les choses inutilement compliquées.

Si vous avez vraiment besoin d'un singleton, vous pouvez généraliser ce private Object result; dans une carte et penser à un moyen d'identifier chaque appel API séparé, comme avec un identifiant de l'appelant.

Enfin, vous pouvez également remplacer le private Object result; par un java.util.concurrent.CompletableFuture. Puis complétez ce futur dans la méthode receiveObject et attendez-le (.get() it) dans someMethod. Ce serait un peu plus idiomatique que d'utiliser une boucle de sommeil thread.

-1

Comment est-il possible que le retour quelque chose qui il n'y a rien à retourner, int someMethod() où est le mot return, et callObject() rien de retour parce qu'il est void. De cette façon, il retournera un objet

public Object someMethod() { 
    return new Object(); 
}