2013-08-19 2 views
3

Dans mon servlet, je tape plusieurs URL pour vérifier leur statut et retourner la réponse à l'utilisateur.Mise en œuvre correcte de Java Future multithread

Frapper des requêtes multipaires prend beaucoup de temps: besoin de threads et de timings. Mais j'ai besoin de mes threads pour obtenir la réponse: utiliser Future pour cette raison.

Mon plan de code:

ExecutorService executor = Executors.newFixedThreadPool(10); 
Future<statusModel> future; 

for (Map.Entry<String, String> url : urls.entrySet()) 
{ 
    try 
    { 
     future = executor.submit(new CallableRequestStatus(url.getValue())); 
     status = (statusModel) future.get(5, TimeUnit.SECONDS); 
     results.add(status); 
    } 
    catch (InterruptedException | ExecutionException | TimeoutException e) 
    { 
     System.out.println("Error<checkServers>: Timeout OR "+e.getMessage()); 
    } 
} 
executor.shutdownNow(); 

Tous les résultats de ma classe appelable est à venir dans l'objet d'état que j'ajouter plus tard à un ArrayList. Mon problème ici est que mon approche me bloque d'exécuter tous les 10 threads en même temps. Je dois attendre 5 secondes pour obtenir mon objet d'état, puis passer à l'URL suivante.

Je pense que mon approche est défectueuse. J'ai essayé de regarder en ligne mais je ne pourrais trouver aucun exemple avec des objets faits sur commande et Arraylist impliqué.

Quelqu'un peut-il m'aider à corriger ma faute. Merci à l'avance

enfin mis à jour mon code (grâce à Sotirios Delimanolis et Kevin):

ExecutorService executor = Executors.newFixedThreadPool(20); 
List<Future<statusModel>> futures = new ArrayList<Future<statusModel>>(); 

for (Map.Entry<String, String> url : urls.entrySet()) 
{ 
    Future<statusModel> future = executor.submit(new CallableRequestStatus(url.getValue())); 
    futures.add(future); 
} 

ArrayList<statusModel> results = new ArrayList<statusModel>(); 
statusModel status; 

int i=0; 

for (Map.Entry<String, String> url : urls.entrySet()) 
{   
    try 
     { 
      status = (statusModel) futures.get(i).get(500, TimeUnit.MILLISECONDS); 
      // do some stuff with status and 

      if(status.getStatusCode()/100 == 2) 
       results.add(status); 
     } 
    catch (InterruptedException | ExecutionException | TimeoutException e) 
     { 
      System.out.println("Error<checkServers>: Timeout OR "+e.getMessage()); 
     } 
i++; 
} 

executor.shutdownNow(); 
System.out.println("Shutdown: "+executor.isShutdown()); 

Espoir pour quelqu'un son utile :)

+6

Ajoutez tous les contrats à terme à un ensemble ou à une liste. Après avoir soumis tous vos callables, parcourez les éléments 'Future' et appelez' get' sans valeur de délai. Votre thread principal bloquera, mais les autres tâches continueront à s'exécuter. Vous attendez essentiellement la durée du callable le plus long. –

+0

Merci Sotirios pour une réponse rapide. J'ai essayé ce que vous avez suggéré mais je suis toujours bloqué quand je boucle sur futureList pour les serveurs qui prennent trop de temps. –

+0

Si vous devez attendre que tous les serveurs répondent et obtiennent tous leurs résultats, c'est la seule manière synchrone de le faire. –

Répondre

2

Vous devez soumettre tout dès le départ, puis attendez séparément. Comme ci-dessous, la gestion des exceptions a été supprimée pour plus de clarté:

ExecutorService executor = Executors.newFixedThreadPool(10); 
List<Future<statusModel>> futures = new ArrayList<>(); 

for (Map.Entry<String, String> url : urls.entrySet()) 
{ 
    futures.add(executor.submit(new CallableRequestStatus(url.getValue()))); 
} 
for (Future<statusModel> f : futures) { 
    results.add((statusModel) f.get(5, TimeUnit.SECONDS)); 
} 
+0

Salut Kevin, Merci ou une réponse rapide. J'ai juste essayé ce que vous et @Sotirios suggéré. Cela ressemble certainement à la bonne façon de mettre en œuvre, mais quand je suis en train de répondre à mes demandes, je peux toujours voir que les demandes sont traitées une par une. Donc, si le serveur 1 stagne ... seulement après que son serveur 2 a été vérifié et le serveur 3 Dans cette approche, si 20 5 servent de blocage pendant 5 secondes, mon temps de réponse est de 25 + secondes. –

+0

Si vous mettez aussi le timeout dans le callable, vous n'avez pas à bloquer sur le get, et vous pouvez simplement tester future.isDone() – lscoughlin

+0

lscoughlin, si je devais attendre dans mon callable, je devrai utiliser get to collect mes résultats Donc, quand je boucle sur ma futureList je vais toujours rester bloqué sur les réponses de timetaking je ne vais pas? –