จะรับ id เธรดจากเธรดพูลได้อย่างไร


131

ฉันมีกลุ่มเธรดคงที่ที่ฉันส่งงานให้ (จำกัด5เธรด) ฉันจะทราบได้อย่างไรว่าเธรดหนึ่งใน5เธรดใดดำเนินการกับงานของฉัน (เช่น "เธรด # 3 จาก5กำลังทำงานนี้")

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

คำตอบ:


230

ใช้Thread.currentThread():

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

3
นี่ไม่ใช่คำตอบที่ต้องการจริงๆ ควรใช้% numThreadsแทน
petrbel

2
@petrbel เขาตอบหัวข้อคำถามได้อย่างดีเยี่ยมและรหัสเธรดก็ใกล้เคียงกันมากพอในความคิดของฉันเมื่อ OP ร้องขอ "something like" thread # 3 of 5 "
CorayThan

หมายเหตุผลลัพธ์ตัวอย่างgetId()คือ14291โดยที่getName()ให้คุณpool-29-thread-7ซึ่งฉันจะโต้แย้งว่ามีประโยชน์มากกว่า
Joshua Pinter

26

คำตอบที่ได้รับการยอมรับตอบคำถามเกี่ยวกับการรับด้าย id แต่มันไม่ได้ช่วยให้คุณทำ "กระทู้ของ X Y" ข้อความ รหัสเธรดจะไม่ซ้ำกันในเธรด แต่ไม่จำเป็นต้องเริ่มจาก 0 หรือ 1

นี่คือตัวอย่างที่ตรงกับคำถาม:

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

และผลลัพธ์:

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

การปรับแต่งเล็กน้อยโดยใช้เลขคณิตโมดูโลจะช่วยให้คุณทำ "เธรด X ของ Y" ได้อย่างถูกต้อง:

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

ผลลัพธ์ใหม่:

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
รหัสเธรด Java รับประกันว่าจะติดกันหรือไม่ ไม่เช่นนั้นโมดูโลของคุณจะทำงานไม่ถูกต้อง
Brian Gordon

@BrianGordon ไม่แน่ใจเกี่ยวกับการรับประกัน แต่รหัสดูเหมือนจะไม่มีอะไรมากไปกว่าการเพิ่มตัวนับภายใน: hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/…
Burhan Ali

6
ดังนั้นหากมีการเตรียมใช้งานเธรดพูลสองเธรดพร้อมกันเธรดในเธรดพูลหนึ่งในนั้นอาจมี ID เช่น 1, 4, 5, 6, 7 และในกรณีนี้คุณจะมีเธรดที่แตกต่างกันสองเธรดที่เหมือนกันโดยมี "ฉันเป็น เธรด n ของข้อความ 5 "
Brian Gordon

@BrianGordon Thread.nextThreadID () ถูกซิงโครไนซ์ดังนั้นนี่จะไม่เป็นปัญหาใช่ไหม
Matheus Azevedo

@MatheusAzevedo ที่ไม่มีส่วนเกี่ยวข้องกับมัน
Brian Gordon

6

คุณสามารถใช้ Thread.getCurrentThread.getId () ได้ แต่ทำไมคุณถึงต้องการทำเช่นนั้นในเมื่ออ็อบเจ็กต์ LogRecordที่จัดการโดย Logger มีเธรด Id อยู่แล้ว ฉันคิดว่าคุณขาดการกำหนดค่าที่บันทึกรหัสเธรดสำหรับข้อความบันทึกของคุณ


1

หากคลาสของคุณสืบทอดมาจากเธรดคุณสามารถใช้เมธอดgetNameและsetNameตั้งชื่อแต่ละเธรดได้ มิฉะนั้นคุณสามารถเพิ่มnameเขตข้อมูลMyTaskและเริ่มต้นในตัวสร้างของคุณได้


1

หากคุณใช้การบันทึกชื่อเธรดจะเป็นประโยชน์ โรงงานด้ายช่วยในเรื่องนี้:

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

เอาท์พุท:

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

1

มีวิธีการรับเธรดปัจจุบัน:

Thread t = Thread.currentThread();

หลังจากที่คุณมีอ็อบเจ็กต์คลาสเธรด (t) คุณสามารถรับข้อมูลที่คุณต้องการโดยใช้เมธอดคลาสเธรด

รหัสเธรดได้รับ:

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

ชื่อกระทู้ได้รับ:

String tName = t.getName(); // e.g. "pool-29-thread-7"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.