Java多线程 - 线程的唯一标识(ID)是什么?

结论

threadSeqNumber是线程的ID,可以通过线程对象的getId方法来获取。

分析

数据库里头,我们建表的时候通常唯一标识叫ID,Thread对象也有ID,可以通过getId来获取。这个ID是自增长的,我们可以查看Thread源代码,下面是我截取出来的代码片段。

public class Thread implements Runnable {
    /* For generating thread ID */
    private static long threadSeqNumber;
    
    private static int threadInitNumber;

    private static synchronized long nextThreadID() {
        return ++threadSeqNumber;
    }

    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }
}

从代码中可以看到有两种ID,分别是threadSeqNumberthreadInitNumberthreadSeqNumber是线程的ID,可以看到这个ID是同步递增的,我们可以在Thread的init方法中看到,每个线程都会分配一个这样的ID。

private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc) {
      
     // ... (省略其它源码内容)
     
     /* Set thread ID */
     tid = nextThreadID();
}

而threadInitNumber是当我们没有给线程起名字的时候,默认会采用Thread-N的格式给线程起名,这里的N就是threadInitNumber。从Thread源码中我们可以看到下面的构造函数,这里只列出来两个与之相关的构造。

public Thread() {
    init(null, null, "Thread-" + nextThreadNum(), 0);
}
public Thread(String name) {
    init(null, null, name, 0);
}

很明显,我们可以发现,如果我们采用这里无参构造,会产生一个格式为Thread-N的默认名称,此时threadInitNumber也会随之递增,如果我们采用有参的构造,threadInitNumber就不会递增。所以我们不要愚蠢的看到默认名称后面的数字,就认为我们当前主线程下开启了这么多个线程,更不要愚蠢的认为这个数字就是线程的ID。这个数字跟ID和线程数没半毛钱关系。
当我们拿到线程的ID以后,就可以根据ID获取到这个线程对象。
如下:

public static void main(String[] args) throws Exception {
		
	// 构造一个线程并启动,取名为"my-thread"
	Thread myThread = new Thread(new Runnable() {
		public void run() {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}, "my-thread");
	myThread.start();
	long myThreadId = myThread.getId();
	System.out.println("my-thread线程ID为:" + myThreadId);
	
	// 拿到当前线程下所有子线程,找出名称为"my-thread"的线程并输出该线程的ID
	// 这串代码用到了activeCount和enumerate方法,在API的介绍中有详细说明
	Thread[] ts = new Thread[Thread.activeCount()];
	Thread.enumerate(ts);
	for(Thread t: ts) {
		if(t.getId() == myThread.getId()) {
			System.out.println("从主线程中找到名为my-thread的线程,线程名称为:" + t.getName() + ", 状态为: " + t.getState());
		}
	}
}

找遍了Thread的方法,没有找到可以直接通过ID或者NAME去获取thread对象的方法,最终采用了这种拙劣的方式。无论这种方式是否最佳,我们根据ID拿到了子线程对象进而可以操作这个子线程。

注意,Thread.enumerate只能拿到非NEW和非TERMINATED状态的子线程。所以这段代码可能没有任何输出。

(完)

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值