2008-11-10 5 views
2

Disons que je fais quelque chose en Java comme:Traitement d'une arrivée à expiration FutureTask

 

RemoteResponse response = null; 
try { 
    FutureTask task new FutureTask(....); 
    executor.execute(task); 
    response = task.get(1000, TimeUnits.MILLISECONDS); 
} 
catch(TimeoutException te) { 
     .. should I do something special here? ... .. what happens to the return value of the task if task.get() throws an exception? ... .. is it ever garbage collected? ..  
} 
 

Ma question est quelque chose ne tient sur RemoteResponse dans le cas où TimeoutException est jeté? Va-t-il récupérer les ordures? Dois-je appeler la méthode cancel() sur la tâche pour que cela se produise?

Répondre

3

Modifier après la question a été révisée:

response est une référence à un RemoteResponse que task est responsable de l'attribution. L'affectation de la valeur de retour à partir d'une méthode ne se produira pas si la méthode a levé une exception, il n'est donc pas nécessaire de traiter de façon spécifique response.

task sera non référencé s'il sort de la portée, soit par une exécution normale, soit si une exception est levée.

Si les ressources allouées par task sont bien enrobés, autrement dit, il n'y a aucune référence externe détenus, et sont libérés (close, release, peu importe), il devrait y avoir aucune fuite de ressources.

Il n'est pas nécessaire d'appeler annuler sauf s'il y a une ressource partagée que le task a exclusivement ou une autre ressource consommable dont le reste de l'application a besoin.

Je noterais au moins le fait que la tâche ne s'est pas terminée dans le temps alloué. Ce que vous faites d'autre dépend des exigences de votre application.

Notez que task continuera à s'exécuter jusqu'à la fin, quel que soit l'appel get.

1

Je pense que la façon de voir le problème est que vous devez revendiquer la ressource en dehors de la FutureTask, de sorte que lorsque vous décidez de l'annuler, vous pouvez forcer la récupération des ressources.

donc:

Resource res = null; 
try { 
resource = ResourceAquirer.claim() 

FutureTask<?> task = new FutureTask<?>(resource); 
executor.execute(task); 
response = task.get(1000, TimeUnits.MILLISECONDS); 
} catch (Exception e) { 
    // logging 
} finally { 
if (resource != null) { 
    resource.release(); 
} 
} 

De cette façon, vous pouvez être sûr que la ressource sera libérée. Il est vraiment frustrant que tout cela ne puisse pas être encapsulé à l'intérieur de la tâche future, mais je ne peux pas trouver la preuve qu'appeler annuler sur un futur site fera en sorte qu'un bloc final soit invoqué dans la FutureTask. (Peut-être que je vais demander cela comme une autre question)

+0

Cela ressemble à une bonne approche. – Dave

+0

Si on appelle Future # cancel() sur une FutureTask et que cet appel annule effectivement l'opération - en supposant qu'elle n'ait pas été annulée ou qu'elle soit déjà terminée - la méthode protégée FutureTask # done() sera appelée. Dans done(), vous pouvez appeler Future # isCancelled() pour voir si vous avez terminé en vertu de l'annulation. En d'autres termes, done() ne sera appelé qu'une fois au maximum. Si vous n'appelez jamais run() ou cancel() sur FutureTask, done() ne sera jamais appelé. – seh