难度
初级
学习时间
30分钟
适合人群
零基础
开发语言
Java
开发环境
- JDK v11
- IntelliJ IDEA v2018.3
友情提示
- 本教学属于系列教学,内容具有连贯性,本章使用到的内容之前教学中都有详细讲解。
- 本章内容针对零基础或基础较差的同学比较友好,可能对于有基础的同学来说很简单,希望大家可以根据自己的实际情况选择继续看完或等待看下一篇文章。谢谢大家的谅解!
1.售票大厅
今天我们开始学习怎么获取和设置线程的名字。
有小伙伴会说:线程还有名字?
嗯,线程它有名字。
我们还是举一个生活中的多线程例子,然后来对比今天要学习的内容。
上图是售票大厅,大家再熟悉不过。其中每一个售票窗口都有自己名字,例如,1号窗口、2号窗口...等等:
如果把每一个售票窗口看作是一个线程,那么售票窗口上的x号窗口就是线程的名字。
2.两种创建线程的方式
前面我们学习了两种创建线程的方式,第一种是继承Thread类:
HiThread类
Main类
第二种是实现Runnable接口:
HiRunnable类
Main类
其中,第一种创建方式我们在《“全栈2019”Java多线程第二章:创建多线程之继承Thread类》一章中学习过;
第二种创建方式我们在《“全栈2019”Java多线程第三章:创建多线程之实现Runnable接口》一章中学习过。
当然了,它们都有自己的匿名内部类创建方式。
Thread的匿名内部类方式一:
Thread的匿名内部类方式二:
Thread的匿名内部类方式一是创建线程并启动一步到位;Thread的匿名内部类方式二是先创建线程对象,然后启动线程,分了两步。
Runnable的匿名内部类方式一:
Runnable的匿名内部类方式二:
Runnable的匿名内部类方式一分了三步,第一步通过匿名内部类方式创建Runnable对象,第二步创建了Thread对象,第三步是启动线程。
Runnable的匿名内部类方式二分了两步,第一步创建Thread对象,并将通过匿名内部类的方式创建Runnable对象传入构造方法参数中,第二步是启动线程。
虽然,这两种方式的第三步都可以一步到位,但是为了大家看得方便,我还是分开写,实际开发中以上所有创建方式都有可能遇到。希望大家留意。
2.获取线程的名称
好了,创建多线程的方式看完了,接下来我们来看看如何获取线程的名称。
在前面章节中,我们说过,在Java中,用Thread类来描述线程。所以,要想获取线程的名称,还得从Thread类下手。
在我们Thread类中有这样一个方法:
我们将getName()方法的注释翻译成中文给大家看看:
getName()方法的作用是返回线程名称。
接下来,我们就来试试。
演示:
请获取线程的名称。
请观察程序代码及结果。
代码:
HiThread类:
Main类:
结果:
程序执行结果出来了,这个结果似乎也没让我们大吃一惊,因为它就是“Thread-”加一个数字标识。
不管怎样,我们还是看看程序代码是怎么写的。
首先,我们自定义了一个线程类HiThread:
然后我们在Main类的main()方法中创建了它的对象:
接着,我们调用其getName()方法,目的是获取线程名称:
最后,我们将获取到的线程名称打印出来:
执行结果:
从程序运行结果来看,我们如果再创建一个线程对象,然后它的线程名称是不是“Thread-1”?这样一直往上累加数字?
来试试。
上述部分程序不变,改写我们的Main类:
运行程序,执行结果:
从运行结果来看,符合我们的预期。
说明我们创建多个线程时,线程默认的名字就是“Thread-x”,其中x是数字,从0开始累加。
3.主线程的名称
在《“全栈2019”Java多线程第一章:认识多线程》一章中,我们知道每一个进程中至少有一个线程,在Java应用程序中,有一个执行Java应用程序的线程叫主线程。
通俗来说,就是每次我们按下这个按钮后:
程序开始执行:
具体去执行我们程序代码的这个线程就是主线程。
为什么要单独用一小节来说主线程?
这一次我们不去讨论主线程,只是主线程它的名称叫“main”。我们这一小节是带大家来获取到主线程并打印它的名称。
其实大家见过主线程,在我们学习异常系列的时候。
接着,我们就来通过异常来找到它。
该程序非常简单,就是计算1除以0的值,大家都知道这会产生异常。我们就是要它产生异常,来运行程序,执行结果:
错误信息:
文字版:
Exception in thread "main" java.lang.ArithmeticException: / by zeroat main.Main.main(Main.java:12)
我们将异常信息翻译成中文
线程“main”中的异常java.lang.ArithmeticException:/ by zeroat main.Main.main(Main.java:12)
大家看见了吗?
线程“main”说的就是主线程。
好,接下来,我们就不通过异常的方式来获取主线程名称。而是通过getName()方法的方式获取线程名称。
这里需要一个方法的支持,那就是Thread类的currentThread()方法:
将注释翻译成中文:
简而言之,currentThread()方法就是获取当前正在执行的线程。
从上图中,我们可以看出:currentThread()方法是静态方法,也就是类方法,可以直接使用类名调用,即Thread.currentThread()。
我们为什么需要了解currentThread()方法?
因为我们要获取当前执行程序代码的线程,然后打印出该线程的名称,所以需要提前了解currentThread()方法。
接下来,我们来演示通过currentThread()方法和getName()方法获取主线程名称。
演示:
请通过currentThread()方法和getName()方法获取主线程名称。
请观察程序代码及结果。
代码:
Main类:
结果:
从运行结果来看,符合我们预期。
简单回顾程序代码,我们在main()方法中第一步通过currentThread()方法获取到当前正在执行程序代码的线程:
然后通过getName()方法获取线程名称:
最后,打印线程名称:
执行结果:
通过currentThread()方法和getName()方法我们获取到主线程名称。
currentThread()方法和getName()方法在实际开发中的使用频率还是可以的,大家应该掌握它们。
4.设置线程名称
上面我们学习了如何获取线程的名称,接下来,我们就来学习如何设置线程的名称。
先来看一张图:
有小伙伴一眼就看出来,这是getName()方法源码。
为什么要看这张图?
因为这张图有一处,不知道发现来没,就是这里:
图上看不清没关系,我们把它写下来:
@see #setName(String)
第一部分“@see”是一个注解,不明白注解是什么的小伙伴没有关系,后续我们会出有关Java注解相关的教学。它里面有一个英语单词see,中文是看的意思。综合来说这个注解的意思是可以参见与之相关的代码。
与谁相关?
@see注解用在哪个地方就是和谁相关,比如现在@see注解用在getName()方法上,意思就是可以参见与getName()方法相关的代码。
相关的代码在哪?
相关的代码指的就是@see后面跟的部分。比如:#setName(String)。
综上所述,我们在使用getName()方法的时候,可以参见和getName()方法密切相关的代码setName()方法。
好了,我们现在就去看看setName()方法。
将注释翻译成中文:
通过注释我们可以一句话描述setName()方法的作用:
setName()方法的作用是设置线程的新名称。
在演示之前,对于上述setName()方法源码图中的注释比较多,下面我们给出一个去掉注释版的setName()方法源码图:
好了,我们来演示setName()方法。
演示:
请设置线程新名称。
请观察程序代码及结果。
代码:
HiThread类:
Main类:
结果:
从运行结果来看,我们成功地为线程设置了新名称。
回顾程序代码,首先,我们自定义了线程类HiThread:
然后,我们在Main类的main()方法创建了HiThread对象:
接着,我们获取了HiThread线程的名称:
然后,打印了HiThread线程的名称:
接着,我们给HiThread线程设置了新名称:
然后,我们又获取了HiThread线程的新名称:
最后,我们打印了HiThread线程的新名称:
执行结果:
从运行结果来看:
“Thread-0”是我们HiThread线程旧名称。
“hi”是我们HiThread线程的新名称。
说实话,sheName()方法没有getName()方法在实际开发中使用的多,一般我们不用这种方式去设置我们的线程名称,一般我们在创建线程的同时,去设置线程的名称。
接下来,我们来看看如何在创建线程的同时设置线程的名称。
5.创建线程的同时设置线程的名称
既然是创建线程的同时设置线程的名称,那么设置线程名称的时机肯定在创建线程的时候。
前面我们学习过创建多线程的两种方式,无论是继承Thread类方式还是实现Runnable接口方式,最后都是绕不开Thread,所以我们还得来Thread类中看看。
我们去Thread类不是瞎看,既然是创建线程的时候,那么肯定是看构造方法或者静态方法,所以我们就去看看Thread类的构造方法或静态方法中有哪些是符合要求的。
首先,Thread类只能通过构造方法来创建对象,所以它里面的静态方法不用看。
下面就把Thread类所有构造方法列出来:
- Thread()
- Thread(Runnable target)
- Thread(Runnable target, String name)
- Thread(String name)
- Thread(ThreadGroup group, Runnable target)
- Thread(ThreadGroup group, Runnable target, String name)
- Thread(ThreadGroup group, Runnable target, String name, long stackSize)
- Thread(ThreadGroup group, Runnable target, String name, long stackSize, boolean inheritThreadLocals)
- Thread(ThreadGroup group, String name)
上述列表中,只要有name参数的构造方法都是符合的,因为name参数的作用就是设置线程名称,于是过滤后:
- Thread(Runnable target, String name)
- Thread(String name)
- Thread(ThreadGroup group, Runnable target, String name)
- Thread(ThreadGroup group, Runnable target, String name, long stackSize)
- Thread(ThreadGroup group, Runnable target, String name, long stackSize, boolean inheritThreadLocals)
- Thread(ThreadGroup group, String name)
ThreadGroup现在没学,后面我们讲到时再说,所以再过滤:
- Thread(Runnable target, String name)
- Thread(String name)
最后只剩下Thread(Runnable target, String name)和Thread(String name)。
下面我们分别来演示这两个构造方法。
Thread(String name)
我们先来看看该构造方法的源码:
将注释翻译成中文:
什么时候使用Thread(String name)构造方法?
在创建线程的同时需要给线程设置名称时使用。
接下来,我们就来演示Thread(String name)构造方法。
演示:
请使用Thread(String name)构造方法创建线程。
请观察程序代码及结果。
代码:
Main类:
结果:
从运行结果来看,符合我们预期。
程序代码也很简单,我们在main()方法中创建了线程并设置它的名称:
然后,获取了该线程的名称:
最后,打印该线程的名称:
执行结果:
“haha”就是我们在创建线程的时候设置的,符合预期。
Thread(String name)构造方法在实际开发中也有用到,希望大家掌握该用法。
Thread(Runnable target, String name)
接下来,我们就来看看Thread(Runnable target, String name)构造方法。
该构造方法有两个参数:Runnable类型的target和String类型的name。前者需要一个实现Runnable接口的对象,后者需要一个字符串(即线程名称)。
下面,我们就来试试Thread(Runnable target, String name)构造方法。
演示:
请使用Thread(Runnable target, String name)构造方法创建线程。
请观察程序代码及结果。
代码:
Main类:
结果:
从运行结果来看,符合我们的预期。
程序代码也很简单,我们在main()方法中首先创建了Runnable对象:
然后使用Thread(Runnable target, String name)构造方法创建线程,所以第一个参数我们将上一步创建好的Runnable对象传进去,然后第二个参数写上线程名称:
接着,我们获取了线程的名称:
最后,我们打印了线程的名称:
执行结果:
“haha”就是我们在创建线程的时候设置的,符合预期。
Thread(Runnable target, String name)构造方法在实际开发中也有用到,希望大家可以掌握它的用法。
总结
- getName()方法的作用是返回线程名称。
- currentThread()方法的作用是获取当前正在执行的线程。
- setName()方法的作用是设置线程的新名称。
- Thread(String name)构造方法在在创建线程的同时需要给线程设置名称时使用。
- Thread(Runnable target, String name)构造方法在创建线程的同时需要传入Runnable对象和线程名称时使用。
至此,Java中获取和设置线程名称相关内容讲解先告一段落,更多内容请持续关注。
答疑
如果大家有问题或想了解更多前沿技术,请在下方留言或评论,我会为大家解答。
上一章
“全栈2019”Java多线程第三章:创建多线程之实现Runnable接口
下一章
“全栈2019”Java多线程第五章:线程睡眠sleep()方法详解
学习小组
加入同步学习小组,共同交流与进步。
- 方式一:关注头条号Gorhaf,私信“Java学习小组”。
- 方式二:关注公众号Gorhaf,回复“Java学习小组”。
全栈工程师学习计划
关注我们,加入“全栈工程师学习计划”。
版权声明
原创不易,未经允许不得转载!