Threads o ThreadPool? Fixed o Dynamic ThreadPool?

8

Ho un programma java che ascolta su una porta per l'input. Basato su Input, chiama un webservice e quindi restituisce un successo / fallimento al programma client.

I fork di un thread per ogni connessione client. La risposta al client che si connette al programma deve essere veloce.

Queste sono le scelte che sto considerando

  1. usa i thread regolari
  2. usa ExecutorService con newFixedThreadPool
  3. usa ExecutorService con newCachedThreadPool

La ragione per cui sto considerando Pools è perché i miei thread sono di breve durata - chiamano semplicemente un webservice, restituiscono il risultato al client e chiudono la connessione.

Non penso che newFixedThreadPool sarebbe la cosa giusta perché le connessioni sarebbero in attesa nelle code per ottenere un thread.

newCachedThreadPool sarebbe stato perfetto tranne per una cosa: i thread muoiono dopo un minuto. Nel mio caso, ricevo esplosioni di connessioni - cioè connessioni multiple e poi ci può essere una pausa per alcuni minuti e poi scoppia di nuovo. Penso che i thread nel CachedThreadPool sarebbero morti e avrebbero dovuto essere ricreati di nuovo - quindi in questo caso, potrebbe funzionare come # 1 a volte.

Idealmente mi sarebbe piaciuto avere newCachedThreadPool con un minimo - cioè un'impostazione che dice che il numero di thread non andrebbe mai al di sotto di dire 20. Quindi i thread inattivi vengono uccisi ma non consentono mai di scendere sotto una soglia minima.

È disponibile qualcosa di simile? O ci sono alternative migliori?

    
posta user93353 06.05.2013 - 07:12
fonte

4 risposte

8

I metodi nella classe Executors sono solo metodi di convenienza per casi di uso comune. Sono disponibili molte più opzioni per la creazione di pool di thread.

Per creare la stessa cosa che Executors.newCachedThreadPool () fa con un minimo di 20 thread (questo viene copiato dal metodo in Executors, con la dimensione del core thread cambiata da 0 a 20).

        return new ThreadPoolExecutor(20, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
    
risposta data 08.05.2013 - 21:15
fonte
4

Domanda interessante.

Vorrei raccomandare contro newCachedThreadPool . Genererà tutti i thread necessari senza limiti superiori. È cattivo!

L'approccio suggerito da Michael sembra buono. Usa ThreadPoolExecutor e usa un numero a tuo agio come dimensione del pool principale. Imposta il numero massimo di thread su qualcosa che desideri tollerare (o che il tuo server può gestire).

Si noti che non c'è praticamente nulla che si possa fare una volta esaurita la risorsa (la coda è piena e il numero massimo di thread funziona). In tal caso, puoi fare una delle due cose: rilasciare nuove connessioni o applicare una contropressione (non accettare nuovi lavori bloccando). TPE per impostazione predefinita genera RejectedExecutionException quando è pieno, ma è facile implementare il comportamento di blocco. Di fatto, ecco un'implementazione open source di BlockingThreadPoolExecutor .

    
risposta data 18.05.2013 - 05:50
fonte
2

Riguardo a RejectedExecutionException:

Invece di un BlockingThreadPoolExecutor, possiamo semplicemente impostare RejectedExecutionHandler in ThreadPoolExecutor per usare CallerRunPolicy gestore.

    
risposta data 15.07.2013 - 20:42
fonte
0

Penso che usare un wrapper su un ThreadPoolExecutor sia un buon modo per andare. Un wrapper in modo da poter esporre un'inizializzazione (come il nome di un pool, il numero di thread, ecc.) E un metodo per aggiungere un'attività (Runnable) a un pool creato in precedenza con uno dei metodi di init.

Il wrapper può cambiare il pool che utilizza senza influenzare altro codice, inoltre può esporre altri metodi come il numero di thread, audit (prima / dopo l'attività) in modo coerente

Puoi anche implementare il tuo factory Thread per il tuo pool, che può avere un nome personalizzato, priorità e almeno hook su un UncaughtExceptionHandler in modo da poter registrare eventuali errori.

nel mio pool wrapper abbiamo metodi come

public static boolean queqeAdd(String poolName, int coreSize, int maxSize, boolean usePriorityQ, String threadNamePrefix, int timeOutSeconds) {...}
public static void execute(String poolName, Runnable command, Integer priority){...}
public static long tasksCount(String poolName) 
public static long tasksCompletedCount(String poolName) 
public static int clearPoolRequest(String poolName, boolean intrpt) 
public static int shutdownPoolRequest(String poolName) 
public static void executeAll(String poolName, List<Runnable> lst) 
    
risposta data 06.05.2013 - 07:50
fonte

Leggi altre domande sui tag