6
votes

Java essayez enfin les variations

Cette question me nagonne pendant un moment, mais je n'ai pas trouvé de réponse complète à ce sujet (par exemple, celui-ci est pour C # Initialisation des ressources jetables à l'extérieur ou à l'intérieur Essayez / enfin ). Considérons deux fragments de code Java suivants: xxx

et deuxième variante xxx

la partie qui m'inquiète est que le fil peut être quelque peu interrompu entre Le moment de la ressource est acquis (par exemple, le fichier est ouvert) mais une valeur résultante n'est pas attribuée à une variable locale respective. Y a-t-il d'autres scénarios que le thread pourrait être interrompu au point supérieur à autre que:

  1. InterromptedException (par exemple, via thread # interruption ()) ou exception OutOfMemoryError est lancée
  2. JVM Sort (par exemple via Kill, System.Exit ())
  3. échec du matériel (ou bogue dans JVM pour la liste complète :)

    J'ai lu que la deuxième approche est quelque peu plus "idiomatique" mais imo dans le scénario ci-dessus, il n'y a pas de différence et dans tous les autres scénarios qu'ils sont égaux.

    Alors la question:

    Quelles sont les différences entre les deux? Que devrais-je préférer si je fais préoccupé par la libération des ressources (en particulier dans des applications fortement multi-threading)? Pourquoi?

    J'apprécierais si quelqu'un me pointe de certaines parties de spécifications Java / JVM prenant en charge les réponses.


0 commentaires

3 Réponses :


0
votes

Mon point de vue est que c'est lorsque vous travaillez avec un runtime géré, tel que Java ou .net, vous ne devriez vraiment pas (et c'est bon!) Préoccupez-vous avec des choses comme votre question particulière. Seulement parce que vous êtes complètement déconnecté du système d'exploitation sous-jacent et de ses API natives. Tout ce que vous avez à savoir est que vous appelez fermable.close () dans votre bloc enfin Le bloc et votre ressource seront toujours libérées.


3 commentaires

Malheureusement, "géré" signifie que cela ne résout qu'une partie des problèmes de gestion des ressources (bien que non négligeable). Si vous escartir beaucoup de ressources, vous devez toujours prendre soin de les libérer car il y a généralement une quantité limitée d'entre elles. Et oui, il y a des serrures. Et des blocages.


@pgras pourquoi voudriez-vous acquérir les ressources dans le essayer bloquer ?? Cela fait du gâchis de votre code.


@TOM Pour être précis, vous devez entrer dans le bloc d'essai pour vous garantir que le bloc enfin sera appelé (vous pouvez obtenir une exception avant d'entrer dans le bloc d'essai). Le moyen facile de garantir qu'il est d'acquérir les ressources à l'intérieur du bloc d'essai.



5
votes

a) Notez que l'interruption du fil avec interruption () ne prendra aucun effet immédiatement et ne peut avoir aucun effet du tout, si le fil étant interrompu ne coopère pas. Il n'ya aucun moyen que le fil quittera l'interruption () lors de l'exécution de: xxx

La seule chose qui se produira est que son drapeau interrompu du fil sera activé.

B) Concernant OutofMemoryError - Je ne vois pas comment cela peut se produire juste après la construction du flux d'entrée. Il peut se produire dans un autre fil, mais cela n'aura aucun effet immédiat sur ce fil. Le problème avec OutofMemoryError, est que votre blocage enfin peut également échouer, car il n'ya pas assez de mémoire pour le compléter ...

c) La seule façon dont je sais qu'un thread peut être interrompu de manière agressive consiste à utiliser le Méthodes obsolètes Thread.Stop () et Thread.stop (lancé). Voir une discussion similaire ici: Est-ce un moyen sûr de libérer des ressources en Java?


0 commentaires

6
votes

Je ne pense pas qu'il y ait une raison d'être concernée:

1) interrompteException (par exemple, via thread # interruption ())

appeler thread.Interrupt () ne cause pas interrompteException doit être jeté spontanément. L'exception n'est lancée que dans des méthodes de blocage spécifiques (et bien documentées); C'est-à-dire de bloquer les méthodes d'E / S et de synchronisation. Cette exception ne peut pas être levée après son retour du constructeur de flux et avant d'entrer dans le bloc d'essai.

ou exception OutofMemoryError est lancée

Si un OutofMemoryError est lancé, vous ne pouvez pas garantir la récupération complète du descripteur de fichier sous-jacent, où que vous placiez le constructeur de flux. Vous ne devriez jamais essayer de récupérer d'une OMOM, donc la question de savoir si le flux est fermé est discutable. En outre, cette exception n'est projetée que sur un fil qui tente d'allouer de la mémoire et cela ne se produit pas à ce stade.

2) Exits JVM (par exemple, via Kill, System.exit ())

Si l'application est terminée de force par un Tuer ou un system.exit () appel, cela n'a pas d'importance si les flux sont fermés correctement. En outre, dans les deux cas, il n'y a aucune garantie que finalement des clauses seront exécutées.

3) échec du matériel (ou bogue dans JVM pour la liste complète :)

Tous les paris sont éteints. Vous n'avez aucun moyen de savoir si quelque chose s'exécutera, sans parler de la finalité.

Il y a une autre situation où un thread pourrait recevoir une exception spontanée à ce stade, avec une attente (naïf) qu'elle pourrait récupérer. C'est-à-dire que certains programmeurs erronés décide d'appeler la méthode dépréciée thread.stop () . Vous pensez peut-être que la mise en place de l'appel du constructeur de flux dans le bloc Essayez aiderait. Mais en réalité, il ne le fera pas, car le FildDeatheath pourrait être soulevé intérieur le constructeur de flux entre ouvrir le fichier sous-jacent et terminer la construction de l'objet Stream. Donc, la FD pourrait de toute façon.

Ceci est juste une seule raison pour laquelle thread.stop () est obsolète. Ne l'utilisez pas.


0 commentaires