2010-07-20 11 views
112

Tengo un grupo de subprocesos fijos al que envío tareas (limitado a subprocesos). ¿Cómo puedo saber cuál de esos hilos ejecuta mi tarea (algo así como "el hilo 3 de está haciendo esta tarea")?¿Cómo obtener la id del hilo de un grupo de subprocesos?

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

Respuesta

182

Usando Thread.currentThread():

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

esto no es en realidad la respuesta deseada; uno debería usar '% numThreads' en su lugar – petrbel

+0

@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 'thread # 3 of 5 ". – CorayThan

1

Si su clase hereda de Thread, puede utilizar métodos getName y setName para nombrar cada hilo. De lo contrario, podría agregar un campo name al MyTask e inicializarlo en su constructor.

6

Puede usar Thread.getCurrentThread.getId(), pero ¿por qué querría hacer eso cuando los objetos gestionados por el registrador LogRecord ya tienen la Id del hilo? Creo que te falta una configuración en algún lugar que registra los Id de la secuencia para tus mensajes de registro.

22

La respuesta aceptada responde a la pregunta sobre cómo obtener una identificación de subproceso, pero no le permite hacer mensajes de "Subproceso X de Y". identificadores de hilo son únicos a través de hilos, pero no necesariamente comienzan desde 0 o 1.

Aquí está un ejemplo que concuerden 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:

[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 

Una ligera inclinación El uso de la aritmética de módulo 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 :

[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

¿Se garantiza que las ID de subproceso de Java sean contiguas? De lo contrario, su módulo no funcionará correctamente. –

+0

@BrianGordon No estoy seguro acerca de una garantía, pero el código no parece ser más que el incremento de un contador interno: http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/ java/lang/Thread.java # l217 –

+5

Entonces, si dos grupos de subprocesos se inicializaron 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 lo haría tener dos hilos diferentes con el mismo mensaje "Soy hilo n de 5". –

0

Si está utilizando el registro, los nombres de los hilos 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 
Cuestiones relacionadas