Java Thread.currentThread().getName() 和 this.getName()区别详解
作者:经典鸡翅 发布时间:2021-10-31 01:46:18
currentThread的详解
currentThread方法是Thread类的一个静态方法,用来获取当前运行的代码段,正在被哪个线程调用。我们先来看一眼源码。
是一个native方法。直接与系统层面做交互。
下面看一段代码
public static void main(String[] args) {
String name = Thread.currentThread().getName();
System.out.println(name);
}
输出的结果为main。
为什么为main呢?
java的项目在启动的时候,会创立一个进程,这个进程同样也是一个线程,在java里面他就叫做main线程。他的名字在设定的时候就是main。我们可以看到上面的代码就是在main方法下执行的,也就是由main线程来执行,所以我们打印出来的名字是main。
创建一个新的线程
来看下面的一行代码,我们创建一个新的线程,并且在线程创建的构造方法和其实际执行的run方法内,增加打印出当前执行线程的名称。
public class TestThread extends Thread {
public TestThread() {
System.out.println("构造方法:" + Thread.currentThread().getName());
}
@Override
public void run() {
System.out.println("run方法:" + Thread.currentThread().getName());
}
public static void main(String[] args) {
TestThread testThread = new TestThread();
testThread.start();
}
}
我们运行一下,看到结果
构造方法:main
run方法:Thread-0
如何理解上述的情况呢?
我们先来看构造方法这一行。
TestThread testThread = new TestThread();
这里我们只是声明了一个线程对象类,这个新的线程没有创建也没有启动,我们仅仅把它理解为一个普通对象即可。那么由于是在main方法里面,那么执行他的一定是main线程,所以可以看到构造方法输出的结果是main。
再来看start方法里面,为什么变成了thread-0了呢。
我们知道java的多线程创建的一种方式就是继承thread类。然后实现里面的run方法。这样当线程start的时候,就会调用内部的start0的本地方法,实际就是会执行run的实现方法。当run方法执行的时候,一定是由我们创建的线程去执行的,而不是main线程,所以我们就可以得知打印出来的是新线程的名字thread0。
为什么新线程的名字为thread0呢?
我们是采用继承thread类的形式来创建线程的,那么在我们构造的时候,一定会执行父类的构造方法。我们是一个空参构造,那么我们就要看下父类的空参构造是什么样的。看一下源码
可以看到,里面有一个name参数,已经给我们拼接了一个thread-后面是加了一个变量,我们继续看看这个变量是什么
一个同步的静态方法,再来看看变量的值。
一个静态的int型变量,由此我们知道int的初始值就是0。我们先获取到了0然后又执行了++。其他线程再次初始化的时候就是从1开始了。因为加了同步锁的关键字,我们不用害怕数据会乱掉。
所以我们就知道了新线程的名字为thread-0的来源。
再看一种带this的情况
public class TestThread extends Thread {
public TestThread() {
System.out.println("构造方法开始!");
System.out.println("构造方法:" + Thread.currentThread().getName());
System.out.println("构造方法的this名称:" + this.getName());
System.out.println("构造方法结束!");
}
@Override
public void run() {
System.out.println("run方法开始!");
System.out.println("run方法:" + Thread.currentThread().getName());
System.out.println("run方法的this名称:" + this.getName());
System.out.println("run方法结束!");
}
public static void main(String[] args) {
TestThread testThread = new TestThread();
testThread.start();
}
}
执行的结果如下:
构造方法开始!
构造方法:main
构造方法的this名称:Thread-0
构造方法结束!
run方法开始!
run方法:Thread-0
run方法的this名称:Thread-0
run方法结束!
我们发现构造的this名称 为thread-0。这个不难理解,this指的是当前对象的名称。因为我们的线程在初始化的时候有了name,所以是thread-0。
创建的线程setName的情况
public class TestThread extends Thread {
public TestThread() {
System.out.println("构造方法开始!");
System.out.println("构造方法:" + Thread.currentThread().getName());
System.out.println("构造方法的this名称:" + this.getName());
System.out.println("构造方法结束!");
}
@Override
public void run() {
System.out.println("run方法开始!");
System.out.println("run方法:" + Thread.currentThread().getName());
System.out.println("run方法的this名称:" + this.getName());
System.out.println("run方法结束!");
}
public static void main(String[] args) {
TestThread testThread = new TestThread();
testThread.setName("test");
testThread.start();
}
}
看一下执行的结果
构造方法开始!
构造方法:main
构造方法的this名称:Thread-0
构造方法结束!
run方法开始!
run方法:test
run方法的this名称:test
run方法结束!
这里有人可能就要问了,为啥构造方法的this名称为thread-0。实际run的时候就变为test了呢。
这是因为我们在构造对象的时候,对象还不完整,没有执行到setName这一步。所以二者不一致。
最后看一段复杂的代码
public class TestThread extends Thread {
public TestThread() {
System.out.println("构造方法开始!");
System.out.println("构造方法:" + Thread.currentThread().getName());
System.out.println("构造方法的this名称:" + this.getName());
System.out.println("构造方法结束!");
}
@Override
public void run() {
System.out.println("run方法开始!");
System.out.println("run方法:" + Thread.currentThread().getName());
System.out.println("run方法的this名称:" + this.getName());
System.out.println("run方法结束!");
}
public static void main(String[] args) {
TestThread testThread = new TestThread();
Thread thread = new Thread(testThread);
System.out.println("新线程thread的名称:" + thread.getName());
thread.setName("test");
thread.start();
}
}
可以看到如下的结果
构造方法开始!
构造方法:main
构造方法的this名称:Thread-0
构造方法结束!
新线程thread的名称:Thread-1
run方法开始!
run方法:test
run方法的this名称:Thread-0
run方法结束!
我们根据结果来看,构造方法的打印,和上面解释的如出一辙。我们重点关注一下新线程的打印,这里为什么是1呢,因为我们上面初始化0之后已经++所以为1。
run方法为test是因为我们实际执行的线程Thread thread = new Thread(testThread);所以我们获取到的名称是thread的名称为test。
那么run方法的this名称为什么是thread-0呢。因为this.getName获取到的是当前对象的名称。我们的当前对象是TestThread。他的线程名称从未被改变过,所以我们拿到了thread-0。
来源:https://www.cnblogs.com/jichi/p/15916171.html


猜你喜欢
- 添加注解效果事务演示注解我们经常会用到,或者在jdk源码中也会看到,例如: @Deprecated以及我们在spring或者spr
- 一、Map接口继承树Map:双列数据,存储key-value对的数据 ---类似于高中的函数:y = f(x)A.HashMap:作为Map
- 棋牌类游戏是目前比较火的游戏之一。今天本文就以实例形式实现洗牌游戏。本文实例所采用的算法是:遍历每个位置上的牌,然后与随机位置上的牌交换。运
- 本篇文章依旧采用小例子来说明,因为我始终觉的,案例驱动是最好的,要不然只看理论的话,看了也不懂,不过建议大家在看完文章之后,在回过头去看看理
- Android 应用冷启动时,需要从Application开始启动,加载时间就会比较长,这段时间里,用户所能看到的就是”白屏“(这是因为默认
- 一、使用方式可以采用Transactional,配置propagation即可。打开org.springframework.transact
- 1.什么是结构化编程编程中只使用三大结构不能使用goto语句1972年美国科学家,发表论文证明所有的程序流程,只需要三大结构完成。2.为什么
- 本文实例讲述了C#在WinForm中使用WebKit传递js对象实现与网页交互的方法。分享给大家供大家参考,具体如下:有个项目要使用WebB
- 一、登录认证基于过滤器链Spring Security的登录验证流程核心就是过滤器链。当一个请求到达时按照过滤器链的顺序依次进行处理,通过所
- springBoot yml文件的list读取问题折腾了很久,记录下。配置如下# 自定义数据上报信息xx: # 机组信息 &nb
- 先附上图片上传的代码jsp代码如下:<form action="${path}/upload/uploadPic.do&qu
- 先说结论:字段类型更改为 'keyword'elasticSearch官方文档中创建index代码如下PUT /my_sto
- 开发中最让人头疼的是应用突然 * ,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误
- 求数组中最大的数的值:1、数组的max函数:class Program { &nb
- 前言我们在很大的项目开发,会发现项目引用的 dll 会很多,我想要按照不同的功能,将不同的 dll 放在不同的文件夹简单的方法是通过修改 A
- using System; using System.Collections.Generic; using System.Linq; usi
- 本文实例为大家分享了Spring MVC接口防数据篡改和重复提交的具体代码,供大家参考,具体内容如下一、自定义一个注解,此注解可以使用在方法
- 一、项目整体介绍:项目整体的结构如下图所示,项目整体采用 springboot + mybatis + jsp + mysql 来完成的,下
- 一、项目简述本系统功能包括:通知公告,老人管理,护工管理,问答管理等等功能。二、项目运行环境配置: Jdk1.8 + Tomcat8.5 +
- 本文实例总结了C#配置文件Section节点处理方法。分享给大家供大家参考。具体如下:很多时候在项目开发中,我们都需要用配置文件来存储一些关