2014-07-09 5 views
0

Je dispose d'un serveur Java qui traite les images comme dans les pages Web demandées par le client.Pool d'exécuteurs dans un serveur Java

Maintenant, le traitement de ces images nécessite du temps et de la mémoire et n nombre de threads entrant dans les images de traitement bloque le serveur.

Maintenant, pour éviter la situation du code qui traite les images, je les ai placées dans une classe Runnable et les appelez à partir d'un pool d'exécuteurs.

Ma question est si l'implémentation ci-dessous est une bonne approche pour exécuter le pool Executor dans un serveur.

L'être de classe Runnable -

public class MyRunnable implements Runnable { 
    private final String id; 

    MyRunnable(String tid) { 
     this.id = tid; 
    } 

    @Override 
    public void run() { 
     NewAlbumImage nai = new NewAlbumImage();     
     nai.save_image(id,false);   
    } 
} 

Le code qui gère la classe Runnable est comme ci-dessous -

newa.NewClass newca = new newa.NewClass(); 
Runnable mr = new MyRunnable(id); 
newca.executor.execute(mr); 

La classe NewClass a une variable d'exécuteur testamentaire statique -

static ExecutorService executor; 

Je m initialise la variable d'exécuteur au démarrage d'applictation de Web et détruit la même à l'application web close -

public class AppNameServletContextListener implements ServletContextListener { 

@Override 
public void contextInitialized(ServletContextEvent sce) { 
    System.out.println("Initializing Executor Pool"); 
    NewClass nc = new NewClass(); 
    nc.executor = Executors.newFixedThreadPool(10); 


} 

@Override 
public void contextDestroyed(ServletContextEvent sce) { 
    NewClass nc = new NewClass(); 
    nc.executor.shutdown(); 
    try { 
     nc.executor.awaitTermination(10L, TimeUnit.MINUTES); 
    } catch (InterruptedException ex) { 
     System.out.println("Executor Pool await Termination exception"); 
    } 
} 
} 

Répondre

0

Vous avez dit que

La classe NewClass a une variable statique exécuteur testamentaire - exécuteur ExecutorService statique;

Je suggère d'utiliser

NewClass.executor.execute(yourRunnableInstance); 

NewClass.executor.shutdown(); 

Ce sera facile à comprendre que executor est un champ statique, vous n'avez pas besoin de créer plusieurs instances NewClass.

Le reste du code semble correct.

+0

Si j'arrête l'exécuteur, où dois-je l'initialiser? –

+0

Je dis que les champs statiques est préférable d'être invoqué par le nom de classe, pas créer une nouvelle instance de classe, qui rendra les gens confus :) 'NewClass.executor = Executors.newFixedThreadPool (10);' 'newFixedThreadPool()' est un static méthode usine, il va initialiser une nouvelle instance 'ExecutorService' pour vous. – haifzhan

+0

Si 10 threads (demandes de page) initialisaient la même variable statique et s'exécutaient et s'arrêtaient, cela ne causerait-il pas de problèmes? –

0

Il y a certaines choses que je considérerais. D'abord, votre exécuteur est statique. Tout d'abord, votre exécuteur est statique. J'utiliserais une sorte de cadre d'injection de dépendance pour injecter correctement votre exécuteur si nécessaire. OU ajoutez-le en tant qu'attribut dans votre contexte de servlet et injectez-le vous-même lorsque la servlet s'initialise.

Créer/arrêt à l'aide ServletContext:

@Override 
public void contextInitialized(ServletContextEvent sce) { 
    ServletContext context = sce.getServletContext(); 
    context.setAttribute("executor", Executors.newCachedThreadPool()); 
} 

@Override 
public void contextDestroyed(ServletContextEvent sce) { 
    ServletContext context = sce.getServletContext(); 
    ExecutorService executor = (ExecutorService)context.getAttribute("executor"); 
    executor.shutdown(); 
} 

En second lieu, vous utilisez un pool de threads fixe. C'est un goulot d'étranglement possible (mais peut-être est-ce délibéré de sauver le CPU?). S'il n'y a pas moyen de redimensionner 10 images en même temps, ça va. Mais si la vitesse à laquelle ils sont traités est plus lente que le taux de demandes, vous allez constater qu'un pool de threads fixe ne fonctionnera pas. En fait, si votre application se joint à la tâche de redimensionnement de la réponse à l'utilisateur, vous avez limité le nombre de demandes possibles à un moment donné au nombre de threads définis. Essayez d'utiliser un pool de threads mis en cache. Les threads sont créés à la demande et meurent de l'inactivité.Enfin, et je pense que c'est plus important, comment votre application évolue-t-elle à l'échelle? Plus vous avez d'utilisateurs, plus il y aura d'images qui seront traitées sur votre serveur web. Votre temps de réponse va se dégrader très rapidement. Aussi peu que trois utilisateurs essayant de redimensionner des images en même temps pourraient utiliser 100% de votre CPU. Je suggère d'agrandir votre image de redimensionnement à une autre machine, un de plus capable.

+0

_Mais si la vitesse à laquelle ils sont traités est plus lente que le taux d'entrée des requêtes, vous allez constater qu'un pool de threads fixe ne va pas fonctionner. Je savais que si cela se produisait, la page attendrait que l'exécuteur n'ait pas fini de traiter l'image. –

Questions connexes