Jak uzyskać identyfikator wątku z puli wątków?


133

Mam stałą pulę wątków, do której przesyłam zadania (ograniczoną do 5 wątków). Jak mogę się dowiedzieć, który z tych 5 wątków wykonuje moje zadanie (na przykład „wątek nr 3 z 5 wykonuje to zadanie”)?

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

Odpowiedzi:


236

Używając Thread.currentThread():

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

3
w rzeczywistości nie jest to pożądana odpowiedź; % numThreadszamiast tego należy użyć
petrbel

2
@petrbel Doskonale odpowiada na tytuł pytania, a identyfikator wątku jest moim zdaniem wystarczająco blisko, gdy OP żąda „czegoś takiego jak 'wątek # 3 z 5”.
CorayThan

Zauważ, że przykładowe wyjście getId()jest 14291tam, gdzie getName()daje pool-29-thread-7, co uważam za bardziej przydatne.
Joshua Pinter

26

Odpowiedź zaakceptowanej odpowiedzi na pytanie o coraz to id wątku, ale nie pozwalają robić „Temat X z Y” wiadomości. Identyfikatory wątków są unikalne we wszystkich wątkach, ale niekoniecznie muszą zaczynać się od 0 lub 1.

Oto przykład pasujący do pytania:

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

i wyjście:

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

Niewielka zmiana przy użyciu arytmetyki modulo pozwoli ci poprawnie wykonać „wątek X z Y”:

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

Nowe wyniki:

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 

6
Czy identyfikatory wątków Java są gwarantowane jako ciągłe? Jeśli nie, twój modulo nie będzie działał poprawnie.
Brian Gordon,

@BrianGordon Nie jestem pewien co do gwarancji, ale kod wydaje się być niczym więcej niż zwiększeniem wewnętrznego licznika: hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/…
Burhan Ali

8
Więc jeśli dwie pule wątków zostały zainicjowane jednocześnie, wątki w jednej z tych pul wątków mogą mieć identyfikatory, na przykład 1, 4, 5, 6, 7 iw tym przypadku miałbyś dwa różne wątki z tym samym „Jestem wątek n z 5 "wiadomość.
Brian Gordon,

@BrianGordon Thread.nextThreadID () jest zsynchronizowany, więc nie byłoby problemu, prawda?
Matheus Azevedo

@MatheusAzevedo To nie ma z tym nic wspólnego.
Brian Gordon

6

Możesz użyć Thread.getCurrentThread.getId (), ale dlaczego miałbyś to robić, gdy obiekty LogRecord zarządzane przez program rejestrujący mają już identyfikator wątku. Myślę, że brakuje gdzieś konfiguracji, która rejestruje identyfikatory wątków dla komunikatów dziennika.


1

Jeśli Twoja klasa dziedziczy po Thread , możesz użyć metod getNamei setNamenazwać każdy wątek. W przeciwnym razie możesz po prostu dodać namepole do MyTaski zainicjować je w swoim konstruktorze.


1

Jeśli korzystasz z logowania, pomocne będą nazwy wątków. Pomaga w tym fabryka nici:

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

Wynik:

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

1

Istnieje sposób pobierania bieżącego wątku:

Thread t = Thread.currentThread();

Po uzyskaniu obiektu klasy Thread (t) możesz uzyskać potrzebne informacje za pomocą metod klasy Thread.

Pobieranie identyfikatora wątku:

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

Pobieranie nazwy wątku:

String tName = t.getName(); // e.g. "pool-29-thread-7"
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.