Thread.currentThread().getName() 和 this.getName()区别详解
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。
总结
currentThread的getName代表当前执行线程的名称,this.getName代表对象的名称。this.getName()实际上返回的是target.getName(),而Thread.currentThread().getName()实际上是thead.getName()。
Thread.currentThread().getName() 和 this.getName()区别详解的更多相关文章
- 基于Java的打包jar、war、ear包的作用与区别详解
本篇文章,小编为大家介绍,基于Java的打包jar.war.ear包的作用与区别详解.需要的朋友参考下 以最终客户的角度来看,JAR文件就是一种封装,他们不需要知道jar文件中有多少个.cla ...
- Android中Intent传值与Bundle传值的区别详解
Android中Intent传值与Bundle传值的区别详解 举个例子我现在要从A界面跳转到B界面或者C界面 这样的话 我就需要写2个Intent如果你还要涉及的传值的话 你的Intent就要写两 ...
- php 去除html标记--strip_tags与htmlspecialchars的区别详解
php 去除html标记--strip_tags与htmlspecialchars的区别详解 作者: 字体:[增加 减小] 类型:转载 时间:2013-06-26 本篇文章是对php中去除html ...
- HTTP POST GET 本质区别详解
HTTP POST GET 本质区别详解 一 原理区别 一般在浏览器中输入网址访问资源都是通过GET方式:在FORM提交中,可以通过Method指定提交方式为GET或者POST,默认为GET提交 Ht ...
- javascript中=、==、===区别详解
javascript中=.==.===区别详解今天在项目开发过中发现在一个小问题.在判断n==""结果当n=0时 n==""结果也返回了true.虽然是个小问题 ...
- [转]ESCAPE()、ENCODEURI()、ENCODEURICOMPONENT()区别详解
escape().encodeURI().encodeURIComponent()区别详解 JavaScript中有三个可以对字符串编码的函数,分别是: escape,encodeURI,encode ...
- phpcms加载系统类与加载应用类之区别详解
<?php 1. 加载系统类方法load_sys_class($classname, $path = ''", $initialize = 1)系统类文件所在的文件路径:/phpcms ...
- Bind和Eval的区别详解
原文:Bind和Eval的区别详解 1.简单描述Eval和Bind的区别 绑定表达式 <%# Eval("字段名") %> <%# Bind("字段名& ...
- 转-HTTP POST GET SOAP本质区别详解
原文链接:HTTP POST GET SOAP本质区别详解 一 原理区别 一般在浏览器中输入网址访问资源都是通过GET方式:在FORM提交中,可以通过Method指定提交方式为GET或者POST,默认 ...
- Go学习——new()和 make()的区别详解(转载)
这篇文章主要介绍了Go语言中new()和 make()的区别详解,本文讲解了new 的主要特性.make 的主要特性,并对它们的区别做了总结,需要的朋友可以参考下 概述 Go 语言中的 new 和 m ...
随机推荐
- Linux系统管理学习实训任务书
1.<Linux系统管理实训任务一之搭建实验基础环境> https://www.toutiao.com/i6763578305091207694/ 2.<Linux系统管理实训任务一 ...
- javascript实现数字整数位每三位一个逗号分隔
Number(1234567).toLocaleString(); //结果"1,234,567" Number(123456789).toLocaleString()//结果&q ...
- 经典变长指令-ModRM
一.如何计算ModRM 0X88 MOV Eb,Gb G:通用寄存器 0X89 MOV Ev,Gv E:寄存器/内存 0X8A MOV Gb,Eb b:字节 0X8B MOV Gv,Ev v:Word ...
- Visaul Studio 2015 MFC 应用程序工程创建
近一段时间开始接触到MFC桌面开发程序,忙完了一段时间的项目开发之后,来整理整理Visaul Studio 2015开发MFC桌面程序的基本功能. 首先从创建软件工程项目开始,Visaul Studi ...
- 【reverse】逆向5 标志寄存器
[reverse]逆向5 标志寄存器 1.引言 通过一个creak.exe文件的爆破,引出现阶段需要学习的知识 2.标志寄存器 标志寄存器有上图这么多个 记住这几个寄存器的位置和名称 下面是6个状态标 ...
- Solon Web 开发,十四、与Spring、Jsr330的常用注解对比
Solon Web 开发 一.开始 二.开发知识准备 三.打包与运行 四.请求上下文 五.数据访问.事务与缓存应用 六.过滤器.处理.拦截器 七.视图模板与Mvc注解 八.校验.及定制与扩展 九.跨域 ...
- 【C++】指针和函数
指针和函数 标签:c++ 目录 指针和函数 一.基本概念 定义: 指针的定义及使用: 二.指针的相互赋值 三.指针的运算 比较大小: 相减: 加减整数类型变量或者常量: 自增自减: 下标运算符[ ]: ...
- 微信小程序-国际化(miniprogram-i18n)
前情提要 最近维护了一个微信小程序的老项目,维护的其中一项是添加国际化.由于踩了蛮多坑,所以就有了这篇文档!!! miniprogram-i18n 对除小程序外的其他框架开发做过国际化的朋友来说i18 ...
- golang中的结构体工厂
1. main包 package main import ( "day01/utils" "fmt" ) //type File struct { // fd ...
- Windows mysql免安装版配置。(版本号-5.6.45);
Windows mysql免安装版配置.(版本号-5.6.45); 来自对 https://blog.csdn.net/weixin_42831477/article/details/81325691 ...