¿Cómo obtener la identificación del hilo de un grupo de hilos?

131

Tengo un grupo de subprocesos fijo al que envío tareas (limitado a 5 subprocesos). ¿Cómo puedo averiguar cuál de esos 5 hilos ejecuta mi tarea (algo como "el hilo 3 de 5 está haciendo esta tarea")?

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

Respuestas:

230

Utilizando Thread.currentThread():

private class MyTask implements Runnable {
    public void run() {
        long threadId = Thread.currentThread().getId();
        logger.debug("Thread # " + threadId + " is doing this task");
    }
}
skaffman
fuente
3
esta no es realmente la respuesta deseada; uno debería usar % numThreadsen su lugar
petrbel
2
@petrbel Está respondiendo perfectamente el título de la pregunta, y el id del hilo está lo suficientemente cerca en mi opinión cuando el OP solicita "algo así como el 'hilo # 3 de 5".
CorayThan
Tenga en cuenta que un resultado de ejemplo de getId()es 14291donde getName()le da pool-29-thread-7, lo que diría que es más útil.
Joshua Pinter
26

La respuesta aceptada responde a la pregunta sobre cómo obtener una identificación de hilo, pero no le permite hacer mensajes de "Hilo X de Y". Los ID de subproceso son únicos en todos los subprocesos, pero no necesariamente comienzan desde 0 o 1.

Aquí hay un ejemplo que coincide con la pregunta:

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();
  }
}

y la salida:

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

Un ligero ajuste utilizando el módulo aritmético le permitirá hacer "hilo X de Y" correctamente:

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

Nuevos resultados:

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 
Burhan Ali
fuente
55
¿Se garantiza que las ID de hilos de Java sean contiguas? Si no, su módulo no funcionará correctamente.
Brian Gordon
@BrianGordon No estoy seguro acerca de una garantía, pero el código no parece más que incrementar un contador interno: hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/…
Burhan Ali
66
Entonces, si se inicializaron dos grupos de subprocesos simultáneamente, los subprocesos en uno de esos grupos de subprocesos podrían tener ID de, por ejemplo, 1, 4, 5, 6, 7 y, en ese caso, tendría dos subprocesos diferentes con el mismo "Soy hilo n del mensaje de 5 ".
Brian Gordon
@BrianGordon Thread.nextThreadID () está sincronizado, por lo que esto no sería un problema, ¿verdad?
Matheus Azevedo
@MatheusAzevedo Eso no tiene nada que ver con eso.
Brian Gordon
6

Puede usar Thread.getCurrentThread.getId (), pero ¿por qué querría hacerlo cuando los objetos LogRecord administrados por el registrador ya tienen el Id. De hilo? Creo que te falta una configuración en algún lugar que registre los ID de hilo para tus mensajes de registro.

Vineet Reynolds
fuente
1

Si su clase hereda de Thread , puede usar métodos getNamey setNamenombrar cada thread. De lo contrario, podría agregar un namecampo MyTaske inicializarlo en su constructor.

Justin Ethier
fuente
1

Si está utilizando el registro, los nombres de subprocesos serán útiles. Una fábrica de hilos ayuda con esto:

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++);
    }
}

Salida:

[   My thread # 0] Main         INFO  A pool thread is doing this task
Vitaliy Polchuk
fuente
1

Existe la forma de obtener el hilo actual:

Thread t = Thread.currentThread();

Después de obtener el objeto de clase Thread (t), puede obtener la información que necesita utilizando los métodos de clase Thread.

Identificación del hilo gettting:

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

Nombre del hilo gettting:

String tName = t.getName(); // e.g. "pool-29-thread-7"
Serg.Stankov
fuente