2010-08-16 5 views
2

Est-il sûr de démarrer un pool de threads dans un constructeur d'objets? Je sais que vous ne devriez pas démarrer un thread à partir d'un constructeur, quelque chose à propos de l'échappement du pointeur "this" (je ne comprends pas exactement cela, mais j'effectuerai d'autres recherches pour essayer de le comprendre).Java démarrant un pool de threads dans le constructeur d'objets

Le code ressemblerait à quelque chose comme ceci:

private ExecutorService pool; 

public handler() 
{ 
    pool = Executors.newCachedThreadPool(); 
} 

public void queueInstructionSet(InstructionSet set) 
{ 
    pool.submit(new Runnable that handles this instruction set); 
} 

Si cela ne fonctionne pas, je pourrais simplement créer cette classe comme Runnable et commencer dans un nouveau thread. Cependant, il semblerait que ce serait ajouter un fil inutile au programme où il n'en a pas vraiment besoin.

Merci.

EDIT:

Merci pour les réponses tout le monde, ils ont certainement contribué à faire de ce sens. Dans mon esprit, il est logique que ce constructeur crée le pool de threads, mais permettez-moi d'expliquer ce que fait ce code, parce que je pense peut-être bizarrement.

Tout le but de cet objet est de prendre des objets "Instruction Sets", et d'agir en conséquence. Les jeux d'instructions proviennent de clients connectés à un serveur. Une fois qu'un ensemble d'instructions complet est reçu d'un client, ce jeu d'instructions est envoyé à cet objet (gestionnaire) pour traitement.

Cet objet gestionnaire contient une référence à chaque objet sur lequel un jeu d'instructions peut agir. Il soumettra l'ensemble d'instructions à un pool de threads, qui trouvera l'objet avec lequel cet ensemble d'instructions souhaite interagir, puis gérera le jeu d'instructions sur cet objet.

Je pourrais gérer l'objet set d'instructions dans le serveur IO, mais mes pensées ont une classe distincte car elle rend le code entier plus lisible, car chaque classe se concentre sur une seule chose spécifique.

Pensées? Conseil?

Merci

Répondre

2

Votre code exemple ne laisse pas « cette » évasion du tout. Il est raisonnablement sûr de démarrer un nouveau thread dans un constructeur (et même utiliser this comme Runnable, ce que vous n'avez pas dans cet exemple) tant que vous êtes sûr que vous avez déjà initialisé l'objet aussi loin que le nouveau thread J'en aurai besoin. Par exemple, la fixation d'un champ final que le nouveau thread s'appuiera sur après à partir du fil serait une très mauvaise idée :)

Fondamentalement, laissant échapper de référence « ce » est généralement méchant, mais pas toujours si . Il y a des situations dans lesquelles c'est sûr. Fait attention. Cela dit, faire démarrer un thread par un constructeur pourrait être considéré comme trop en faire dans le constructeur. Il est difficile de dire si c'est approprié dans ce cas ou non - nous n'en savons pas assez sur ce que fait votre code.

EDIT: Oui, après avoir lu les informations supplémentaires, je pense que c'est correct. Vous devriez probablement avoir une méthode pour fermer le pool de threads.

+0

Merci, ça aide. J'ai mis à jour le PO avec ce que fait ce code. Je pense qu'il est logique d'avoir le constructeur créer le pool de threads, mais je suis assez nouveau à ce sujet et accueillerais tout conseil que je peux obtenir :) – vimalloc

+0

@kyena: OK, la réponse éditée. Fondamentalement, il semble que ce soit probablement correct. Votre classe est en fait * un * pool de threads (via la composition). –

+0

Merci! J'apprécie l'aide :) – vimalloc

1

Je suis d'accord avec Jon.De plus, permettez-moi de préciser que vous ne lancez aucune action sur le pool de threads dans le constructeur. Vous instanciez le pool de threads, mais il n'a aucune tâche à exécuter à ce stade. Par conséquent, tel qu'écrit, vous n'allez pas avoir quelque chose commencer à fonctionner sur cette instance avant qu'il ne finisse la construction.

1

Il semble que le pool de threads soit possédé et utilisé par l'objet; les threads ne seraient pas transmis hors de l'objet. Si c'est le cas, cela ne devrait pas poser de problème.

Les constructeurs créent un objet et initialisent son état. Je ne peux pas imaginer un cas d'utilisation où des processus de longue durée sont nécessaires pour le faire.

Je peux voir où un objet pourrait interagir avec un pool de threads pour accomplir une tâche, mais je ne vois pas le besoin que cet objet possède le pool de threads.

Plus de détails pourraient aider.

+0

Merci, cela aide. J'ai mis à jour le PO avec ce que ce code fait spécifiquement concernant le pool de threads. Je pense qu'il est logique d'avoir cet objet propriétaire du pool de threads, mais je suis assez nouveau à ce sujet et j'accueillerais tout conseil que je peux obtenir :) – vimalloc

0

Je pense que c'est OK pour démarrer un pool de threads dans le constructeur de l'objet tant que cet objet gère entièrement la durée de vie de ce pool de threads.

Si vous allez dans cette voie, vous devrez travailler dur supplémentaire pour fournir les garanties suivantes:

  1. Si vous constructeur lève une exception (à la fois d'exécution et Coché), vous devez avoir un code de nettoyage dans le constructeur cela ferme le pool de threads. Si vous ne le faites pas et créez un pool de threads avec des threads non-démon, par exemple, un petit programme de console qui utilise votre objet peut rester éternel, laissant ainsi s'échapper de précieuses ressources système.
  2. Vous devez fournir quelque chose que j'appelle destructor méthode, similaire à close en Java I/O. Je l'appelle habituellement releaseResources. Notez que finalize n'est pas un substitut à cette méthode, car elle est appelée par GC, et pour un objet avec une empreinte mémoire raisonnablement petite, elle ne peut jamais être appelée.
  3. Lorsque vous utilisez cet objet suit ce modèle

->

MyThreadPoolContainer container = 
    new MyThreadPoolContainer(... args to initialize the object...); 

try 
{ 
    methodThatUsesContainer(container); 
} 
finally 
{ 
    container.releaseResources(); 
} 
  1. Document qui objet constructeur alloue des ressources limitées et la méthode destructor doit être appelé explicitement pour empêcher leur fuite.
Questions connexes