2011-07-21 3 views
2

Je sais que finalize() est appelé chaque fois qu'une instance de classe est collectée par le garbage collector. Cependant, je suis un peu confus lorsque je passe une instance d'une classe à un autre thread via une file d'attente.quand est-ce que finalize() sera appelé sur mon instance de classe dans ce scénario?

Disons que c'est un squelette de Thread1:

for(i=0; i<1000; i++) { 
    Packet pkt = new Packet(); // instance of class 
    pkt.id = i; 
    thread2.queue.put(pkt); 
} 

Ensuite, le fil 2 va supprimer le paquet de la file d'attente et d'effectuer des opérations longues. Est-ce que ce deuxième thread obtient une "copie" du paquet, ou est-ce par une forme de référence? L'important est que, si c'est par copie, le finalize() sur l'instance créée dans le thread 1 peut être appelé avant que le thread 2 soit fait avec le paquet. Si c'est par référence, je suis garanti que finalize() n'est appelé qu'une seule fois pour l'information contenue dans le paquet.

Cet exemple de base peut ne pas montrer l'importance, mais je stocke un pointeur C (à partir de JNI) dans le paquet pour détruire de la mémoire lorsque j'en ai fini avec l'objet. Si elle est transmise par copie, la mémoire peut être détruite avant que le second thread ne soit terminé. Si elle est passée par référence, elle ne devrait être détruite que lorsque le GC verra qu'il n'est plus utilisé par les deux threads (mon comportement désiré). Si ce dernier scénario n'est pas garanti, je n'utiliserai pas finalize() et j'utiliserais autre chose mais ce sera plus complexe.

+0

La comparaison C/++ la plus proche pour les arguments de la méthode java est qu'il s'agit d'un pointeur transmis par une valeur. C'est donc par copie, mais c'est une copie du pointeur. (Dont la seule opération est à déréférencer.) Tant qu'il y a un pointeur quelque part dans le système qui pointe vers l'emplacement de votre objet, cet emplacement ne sera pas collecté. – Affe

+0

Je vous suggère fortement d'ajouter une méthode de nettoyage à Packet pour nettoyer le C-pointeur, et ne pas compter sur la méthode finalize ou même avoir une méthode de finalisation –

Répondre

6

Le deuxième thread reçoit la même instance d'objet réel. Vous êtes à l'abri de la finalisation prématurée.

Il reçoit une copie de la référence d'objet, si vous voulez penser de cette façon. En outre, finalize n'est pas nécessairement exécuté lorsque le garbage collector trouve que l'objet est devenu corrompu - la machine virtuelle est libre de l'exécuter ultérieurement et de récupérer la mémoire quelque temps après cela. Vous ne pouvez vraiment pas compter quand finalize sera exécuté. Cependant, puisque ce qui vous intéresse est de savoir que finalizene sera pas appelé avant que le second thread ne finisse avec l'objet, cela n'a pas d'importance. Mais ça vaut le coup de savoir!

+0

génial! merci beaucoup pour la réponse rapide. cela simplifie énormément les choses pour moi :) – gnychis

+1

L'objet ne sera pas collecté avant l'exécution de finalize()! Les objets qui remplacent la finalisation seront placés dans une file d'attente de finalisation gérée dans un thread de priorité basse. C'est une autre raison pour laquelle vous devriez éviter finalize(). –

+0

@Damokles: Tout à fait correct, bien sûr. Mon phrasé était bâclé, merci de le signaler. Je l'ai reformulé pour, espérons-le, être plus correct. –

Questions connexes