Come ottenere l'ID thread da un pool di thread?


131

Ho un pool di thread fisso a cui invio le attività (limitato a 5 thread). Come posso scoprire quale di quei 5 thread esegue il mio compito (qualcosa come "thread n. 3 di 5 sta facendo questo compito")?

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?
    }
}

Risposte:


230

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
questa non è in realtà la risposta desiderata; si dovrebbe usare % numThreadsinvece
petrbel

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

Nota, un esempio di output getId()è 14291dove getName()ti dà pool-29-thread-7, che direi che è più utile.
Joshua Pinter,

26

La risposta accettata risponde alla domanda su come ottenere a ID thread, ma non ti consente di fare messaggi "Thread X di Y". Gli ID thread sono univoci tra i thread, ma non necessariamente iniziano da 0 o 1.

Ecco un esempio che corrisponde alla 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:

burhan@orion:/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

Una leggera modifica usando l'aritmetica del modulo ti permetterà di fare correttamente "thread X of Y":

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

Nuovi risultati:

burhan@orion:/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 

5
Gli ID thread Java sono garantiti contigui? In caso contrario, il modulo non funzionerà correttamente.
Brian Gordon,

@BrianGordon Non sono sicuro di una garanzia, ma il codice sembra nient'altro che incrementare un contatore interno: hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/…
Burhan Ali

6
Quindi, se due pool di thread sono stati inizializzati contemporaneamente, i thread in uno di quei pool di thread potrebbero avere ID, ad esempio 1, 4, 5, 6, 7 e in tal caso si avrebbero due thread diversi con lo stesso "I am thread n of 5 "message.
Brian Gordon,

@BrianGordon Thread.nextThreadID () è sincronizzato, quindi questo non sarebbe un problema, giusto?
Matheus Azevedo,

@MatheusAzevedo Non c'entra niente.
Brian Gordon,

6

Puoi usare Thread.getCurrentThread.getId (), ma perché dovresti farlo quando gli oggetti LogRecord gestiti dal logger hanno già l'ID thread. Penso che ti manchi una configurazione da qualche parte che registra gli ID thread per i tuoi messaggi di registro.


1

Se la tua classe eredita da Thread , puoi usare metodi getNamee setNamenominare ogni thread. Altrimenti potresti semplicemente aggiungere un namecampo MyTaske inizializzarlo nel tuo costruttore.


1

Se si utilizza la registrazione, i nomi dei thread saranno utili. Una fabbrica di thread aiuta in 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++);
    }
}

Produzione:

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

1

C'è il modo di ottenere il thread corrente:

Thread t = Thread.currentThread();

Dopo aver ottenuto l'oggetto della classe Thread (t), è possibile ottenere le informazioni necessarie utilizzando i metodi della classe Thread.

ID discussione ottenendo:

long tId = t.getId(); // e.g. 14291

Nome discussione ottenendo:

String tName = t.getName(); // e.g. "pool-29-thread-7"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.