2011-09-13 7 views
7

Ho una domanda su Java e la concorrenza.Pool di thread e thread locali in cache Java

Diciamo che ho una variabile ThreadLocal chiamata a. E io uso un CachedThreadPool per ottenere nuovi thread. Quando un thread è riutilizzato, cosa succede alla variabile ThreadLocal? mantiene lo stesso valore (perché è uno stesso thread) o inizia vuoto (come se il thread fosse nuovo)?

Grazie

risposta

10

Per impostazione predefinita, ThreadLocals viene riutilizzato insieme al thread. Se li avete bisogno di essere essere reinizializzata è possibile farlo eseguendo l'override dei metodi indicate di seguito:

from javadoc for java.util.concurrent.ThreadPoolExecutor

metodi Hook Questa classe fornisce protetto ridefinita BeforeExecute (java.lang.Thread, java. lang.Runnable) e afterExecute (java.lang.Runnable, java.lang.Throwable) metodi che vengono chiamati prima e dopo l'esecuzione di ogni attività. Questi possono essere usati per manipolare l'ambiente di esecuzione; ad esempio, reinizializzazione di ThreadLocals, raccolta di statistiche o aggiunta di voci di registro. Inoltre, il metodo terminated() può essere sovrascritto per eseguire qualsiasi elaborazione speciale che deve essere eseguita una volta che l'Executor è terminato completamente. Se i metodi di hook o callback generano eccezioni, i thread dei worker interni possono a loro volta fallire e terminare bruscamente.

+1

Un problema risolvibile che vedo qui è che ThreadPoolExecutor deve essere a conoscenza dei locali dei thread. Tipo di brutta separazione. Può essere risolto da un osservabile che genera un evento una volta che un thread termina l'esecuzione. Un thread locale specifico può registrare (observer) eseguire una pulizia una volta che viene attivato l'evento afterExecute. –

3

Se il filo viene restituita al pool, la variabile ThreadLocal saranno ancora attaccate ad esso. Quando si utilizza ThreadLocals con i pool, è necessario fare attenzione a essere in grado di impostare quando il thread viene estratto dal pool e disinserito prima di essere restituito.

2

È possibile cancellare il pool locale di thread per un thread utilizzando la riflessione. Si può fare

public static void clearAllThreadLocals() { 
    try { 
     Field threadLocals = Thread.class.getDeclaredField("threadLocals"); 
     threadLocals.setAccessible(true); 
     threadLocals.set(Thread.currentThread(), null); 
    } catch (Exception e) { 
     throw new AssertionError(e); 
    } 
}