Làm thế nào để có được id luồng từ một nhóm luồng?


131

Tôi có một nhóm chủ đề cố định mà tôi gửi nhiệm vụ (giới hạn trong 5 chủ đề). Làm cách nào tôi có thể tìm ra một trong 5 luồng đó thực thi nhiệm vụ của mình (đại loại như "luồng số 3 trên 5 đang thực hiện nhiệm vụ này")?

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

Câu trả lời:


230

Sử dụng Thread.currentThread():

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

3
Đây thực sự không phải là câu trả lời mong muốn; người ta nên sử dụng % numThreadsthay thế
petrbel

2
@petrbel Anh ấy trả lời tiêu đề câu hỏi một cách hoàn hảo và theo tôi, chủ đề id gần đủ khi OP yêu cầu "một cái gì đó giống như 'chủ đề số 3 trên 5".
CorayThan

Lưu ý, một ví dụ đầu ra getId()14291nơi getName()cung cấp cho bạn pool-29-thread-7, mà tôi sẽ tranh luận là hữu ích hơn.
Joshua Pinter

26

Câu trả lời được chấp nhận trả lời câu hỏi về việc một thread id, nhưng nó không cho phép bạn làm "Chủ đề X của Y" tin nhắn. Id chủ đề là duy nhất trên các chủ đề nhưng không nhất thiết phải bắt đầu từ 0 hoặc 1.

Đây là một ví dụ phù hợp với câu hỏi:

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

và đầu ra:

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

Một tinh chỉnh nhỏ sử dụng số học modulo sẽ cho phép bạn thực hiện "luồng X của Y" một cách chính xác:

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

Kết quả mới:

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
Các ID luồng Java có được đảm bảo liền kề nhau không? Nếu không, modulo của bạn sẽ không hoạt động chính xác.
Brian Gordon

@BrianGordon Không chắc về một bảo lãnh, nhưng mã dường như không có gì hơn incrementing một truy cập nội bộ: hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/...
Burhan Ali

6
Vì vậy, nếu hai nhóm luồng được khởi tạo đồng thời, các luồng trong một trong các nhóm luồng đó có thể có ID của, ví dụ: 1, 4, 5, 6, 7 và trong trường hợp đó, bạn sẽ có hai luồng khác nhau với cùng một "Tôi là chủ đề n của 5 "tin nhắn.
Brian Gordon

@BrianGordon Thread.nextThreadID () được đồng bộ hóa, vì vậy điều này sẽ không thành vấn đề, phải không?
Matheus Azevedo

@MeditusAzevedo Điều đó không có gì để làm với nó.
Brian Gordon

6

Bạn có thể sử dụng Thread.getCienThread.getId (), nhưng tại sao bạn muốn làm điều đó khi các đối tượng LogRecord được quản lý bởi logger đã có Id luồng. Tôi nghĩ rằng bạn đang thiếu một cấu hình ở đâu đó ghi nhật ký Id luồng cho thông điệp tường trình của bạn.


1

Nếu lớp của bạn kế thừa từ Thread , bạn có thể sử dụng các phương thức getNamesetNameđặt tên cho từng luồng. Nếu không, bạn chỉ có thể thêm một nametrường vào MyTaskvà khởi tạo nó trong hàm tạo của bạn.


1

Nếu bạn đang sử dụng đăng nhập thì tên chủ đề sẽ hữu ích. Một nhà máy luồng giúp với điều này:

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

Đầu ra:

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

1

Có cách nhận chủ đề hiện tại:

Thread t = Thread.currentThread();

Sau khi bạn đã có đối tượng lớp Thread (t), bạn có thể nhận thông tin bạn cần bằng các phương thức lớp Thread.

ID chủ đề sắp xếp:

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

Tên chủ đề gettting:

String tName = t.getName(); // e.g. "pool-29-thread-7"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.