2010-07-20 14 views
112

Ho un pool di thread fisso a cui invio attività (limitato a thread). Come posso scoprire quale di queste thread esegue la mia attività (qualcosa del tipo "il thread n. 3 di sta facendo questa attività")?Come ottenere l'ID del thread da un pool di thread?

ExecutorService taskExecutor = Executors.newFixedThreadPool(5); 

//in infinite loop: 
taskExecutor.execute(new MyTask()); 
.... 

private class MyTask implements Runnable { 
    public void run() { 
     logger.debug("Thread # XXX is doing this task");//how to get thread id? 
    } 
} 

risposta

182

Utilizzando Thread.currentThread():

private class MyTask implements Runnable { 
    public void run() { 
     long threadId = Thread.currentThread().getId(); 
     logger.debug("Thread # " + threadId + " is doing this task"); 
    } 
} 
+3

questo non è in realtà la risposta desiderata; si dovrebbe usare '% numThreads' invece – petrbel

+0

@petrbel Sta rispondendo perfettamente al titolo della domanda, e l'id del thread è abbastanza vicino secondo me quando l'OP richiede" qualcosa come 'thread # 3 di 5 ". – CorayThan

1

Se la classe eredita da Thread, è possibile utilizzare metodi getName e setName per citarne ogni thread. In caso contrario, è sufficiente aggiungere un campo name a MyTask e inizializzarlo nel costruttore.

6

È possibile utilizzare Thread.getCurrentThread.getId(), ma perché si desidera farlo quando gli oggetti LogRecord gestiti dal registratore hanno già l'ID del thread. Penso che manchi una configurazione da qualche parte che registra gli ID dei thread per i tuoi messaggi di log.

22

La risposta accettata risponde alla domanda sull'ottenere a id del thread, ma non consente di eseguire messaggi "Thread X of Y". ids filetto sono unici attraverso i thread ma non necessariamente partono da 0 o 1.

Ecco un esempio abbinando la domanda:

import java.util.concurrent.*; 
class ThreadIdTest { 

    public static void main(String[] args) { 

    final int numThreads = 5; 
    ExecutorService exec = Executors.newFixedThreadPool(numThreads); 

    for (int i=0; i<10; i++) { 
     exec.execute(new Runnable() { 
     public void run() { 
      long threadId = Thread.currentThread().getId(); 
      System.out.println("I am thread " + threadId + " of " + numThreads); 
     } 
     }); 
    } 

    exec.shutdown(); 
    } 
} 

e l'output:

[email protected]:/dev/shm$ javac ThreadIdTest.java && java ThreadIdTest 
I am thread 8 of 5 
I am thread 9 of 5 
I am thread 10 of 5 
I am thread 8 of 5 
I am thread 9 of 5 
I am thread 11 of 5 
I am thread 8 of 5 
I am thread 9 of 5 
I am thread 10 of 5 
I am thread 12 of 5 

Un leggero aggiustamento utilizzando l'aritmetica modulo ti consente di eseguire correttamente "Thread X of Y":

// modulo gives zero-based results hence the +1 
long threadId = Thread.currentThread().getId()%numThreads +1; 

Nuovi risultati :

[email protected]:/dev/shm$ javac ThreadIdTest.java && java ThreadIdTest 
I am thread 2 of 5 
I am thread 3 of 5 
I am thread 3 of 5 
I am thread 3 of 5 
I am thread 5 of 5 
I am thread 1 of 5 
I am thread 4 of 5 
I am thread 1 of 5 
I am thread 2 of 5 
I am thread 3 of 5 
+4

Gli ID thread Java sono garantiti come contigui? In caso contrario, il tuo modulo non funzionerà correttamente. –

+0

@BrianGordon Non sono sicuro di una garanzia, ma il codice non sembra altro che l'incremento di un contatore interno: http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/ java/lang/Thread.java # l217 –

+5

Quindi, se due pool di thread sono stati inizializzati contemporaneamente, i thread in uno di questi pool di thread potrebbero avere ID, ad esempio 1, 4, 5, 6, 7 e in tal caso si avere due thread differenti con lo stesso messaggio "I am thread n of 5". –

0

Se si utilizza la registrazione, i nomi dei thread saranno utili. Una fabbrica filo aiuta con questo:

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.ThreadFactory; 

public class Main { 

    static Logger LOG = LoggerFactory.getLogger(Main.class); 

    static class MyTask implements Runnable { 
     public void run() { 
      LOG.info("A pool thread is doing this task"); 
     } 
    } 

    public static void main(String[] args) { 
     ExecutorService taskExecutor = Executors.newFixedThreadPool(5, new MyThreadFactory()); 
     taskExecutor.execute(new MyTask()); 
     taskExecutor.shutdown(); 
    } 
} 

class MyThreadFactory implements ThreadFactory { 
    private int counter; 
    public Thread newThread(Runnable r) { 
     return new Thread(r, "My thread # " + counter++); 
    } 
} 

uscita:

[ My thread # 0] Main   INFO A pool thread is doing this task 
Problemi correlati