2010-02-25 6 views
15

Je voudrais avoir un ScheduledThreadPoolExecutor qui arrête également le dernier thread s'il n'y a pas de travail à faire, et crée (et maintient les discussions en vie pendant un certain temps) s'il y a de nouvelles tâches. Mais une fois qu'il n'y a plus de travail à faire, il faut rejeter tous les threads.ScheduledThreadPoolExecutor et corePoolSize 0?

Je l'ai créé naïvement comme new ScheduledThreadPoolExecutor(0) mais par conséquent, aucun thread n'est jamais créé, ni aucune tâche planifiée est jamais exécutée.

Quelqu'un peut-il me dire si je peux atteindre mon objectif sans écrire mon propre emballage autour de la ?

Merci d'avance!

+1

Il semble que vous vouliez quelque chose qui créerait et détruirait des threads comme un 'ExecutorService' de' Executors.newCachedThreadPool() ', sauf que vous voudriez qu'il implémente l'interface' ScheduledExecutorService' au lieu de seulement 'ExecutorService' interface. Est-ce un résumé précis? –

+0

En fait, oui, il est un résumé tout à fait exact. –

Répondre

14

En fait, vous pouvez le faire, mais sa non évidente:

  • Créer une nouvelle ScheduledThreadPoolExecutor
  • Dans le constructeur définir les fils de base au nombre maximal de threads que vous souhaitez
  • définir la KeepAliveTime de l'exécuteur
  • et, enfin, de permettre aux fils d'âme Timeout

    m_Executor = new ScheduledThreadPoolExecutor (16,null); 
    m_Executor.setKeepAliveTime (5, TimeUnit.SECONDS); 
    m_Executor.allowCoreThreadTimeOut (true); 
    

    Cela fonctionne uniquement avec Java 6 si

+0

Un grand merci, qui semble tout à fait exactement comme ce que je dois. –

7

Je suppose que rien de ce qui est prévu dans java.util.concurrent ne le fera pour vous, simplement parce que si vous avez besoin d'un service d'exécution planifié, vous avez souvent des tâches récurrentes à effectuer. Si vous avez une tâche récurrente, alors il habituellement a plus de sens de garder le même fil autour et l'utiliser pour la prochaine récurrence de la tâche, plutôt que de démolir votre fil et d'en avoir un nouveau à la prochaine récurrence . Bien sûr, un exécuteur programmé pourrait être utilisé pour insérer des retards entre des tâches non récurrentes, ou il pourrait être utilisé dans les cas où les ressources sont si rares et la récurrence est si rare qu'il est logique de détruire tous vos threads jusqu'à le nouveau travail arrive. Donc, je peux voir des cas où votre proposition aurait certainement du sens.

Pour mettre en œuvre cela, je envisagerais d'essayer d'encapsuler un pool de threads mis en cache de Executors.newCachedThreadPool avec un service d'exécution planifiée à un seul thread (par exemple, new ScheduledThreadPoolExecutor(1)). Les tâches peuvent être planifiées via le service de l'exécuteur planifié, mais les tâches planifiées seront encapsulées de telle sorte que, plutôt que de les exécuter par l'exécuteur programmé monothread, l'exécuteur single-thread les remettra au pool de threads mis en cache exécution. Ce compromis vous donnerait un maximum de threads quand il n'y a absolument aucun travail à faire, et il vous donnerait autant de threads que nécessaire (dans les limites de votre système, bien sûr) quand il y a beaucoup de choses à faire du travail à faire.

+0

Merci pour la réponse. Ellaborated En fait, j'utilise le ScheduledThreadPool pour les opérations retardées, pas pour les actions répétées. Et la plupart des actions sont des actions ponctuelles et je ne voudrais pas créer un fil à chaque fois et je ne voudrais aussi partager un ScheduledExecutorService manuellement explicitement entre les différentes classes qui ont besoin de le faire. –

8

La lecture des javadocs de ThreadPoolExecutor pourrait suggérer que la solution d'Alex V est correct. Cependant, cela entraînera inutilement la création et la destruction de threads, rien de tel qu'un pool de threads encaissés. Le ScheduledThreadPool n'est pas conçu pour fonctionner avec un nombre variable de threads. Après avoir regardé la source, je suis sûr que vous finirez par engendrer un nouveau fil presque chaque fois que vous soumettez une tâche. La solution de Joe devrait fonctionner même si vous ne faites que soumettre des tâches en retard.

PS.Je surveillais vos threads pour m'assurer que vous ne gaspilliez pas de ressources dans votre implémentation actuelle.

5

Ce problème est un bogue connu dans ScheduledThreadPoolExecutor (Bug ID 7091003) et a été corrigé en Java 7u4. Bien que looking at the patch, le correctif est que « au moins un fil est démarré même si corePoolSize est 0. »