public class CurrentThreadTest {
public static void main(String[] args) {
// System.out.println(Thread.currentThread().getName());
Thread td = new TestThread();
td. run();
}
}
class TestThread extends Thread{
public TestThread(){
System.out.println(" 构造函数:" + Thread.currentThread().getName());
}
@Override
public void run() {
System.out.println("run:" + Thread.currentThread().getName());
}
}
构造函数:main
run:main
构造函数,是主线程main调用
run方法,不是启动线程的方法,直接用对象调用,也是主线程调用
start方法,是启动线程的方法,由当前线程调用。run方法是自动调用的方法
=============================================================================================================
public class CountOperate extends Thread {
public CountOperate() {
System.out.println("CountOprrate -----> begin");
System.out.println("CurrentThread:" + Thread.currentThread().getName());
System.out.println("This Name:" + this.getName());
System.out.println("CountOprrate -----> end");
}
@Override
public void run() {
System.out.println("Run -----> begin");
System.out.println("CurrentThread:" + Thread.currentThread().getName());
System.out.println("This Name:" + this.getName());
System.out.println("Run -----> end");
}
public static void main(String args[]) {
CountOperate ce = new CountOperate();
ce.setName("A");
ce.start();
}
}
运行结果如下
CountOprrate -----> begin
CurrentThread:main
This Name:Thread-0 //默认的线程名字
CountOprrate -----> end
Run -----> begin
CurrentThread:A //重新设置线程名字
This Name:A
Run -----> end
==============================================================================================================
public class CountOperate extends Thread {
public CountOperate() {
System.out.println("CountOprrate -----> begin");
System.out.println("CurrentThread:" + Thread.currentThread().getName());
System.out.println("This Name:" + this.getName());
System.out.println("CountOprrate -----> end");
}
@Override
public void run() {
System.out.println("Run -----> begin");
System.out.println("CurrentThread:" + Thread.currentThread().getName());
System.out.println("This Name:" + this.getName());
System.out.println("Run -----> end");
}
public static void main(String args[]) {
CountOperate ce = new CountOperate(); //创建的线程对象 0
Thread td = new Thread(ce); //又封装了一个线程对象1
td.setName("A");
td.start();
}
CountOprrate -----> begin
CurrentThread:main
This Name:Thread-0 //第一个构造函数调用的时候CountOperate ce = new CountOperate(); //创建的线程对象 0,this.getName是第一个线程0
CountOprrate -----> end
Run -----> begin
CurrentThread:A //调用start方法后,线程名字改为A,若不设置线程名字,默认是Thread-1
This Name:A
Run -----> end
CountOprrate -----> begin
CurrentThread:main
This Name:Thread-0
CountOprrate -----> end
Run -----> begin
CurrentThread:Thread-1
This Name:Thread-0
Run -----> end
============================================================
剖析:
首先要清楚thread和t1是两个完全不同的对象,他俩之间唯一的关系就是把thread传递给t1对象仅仅是为了让t1调用thread对象的run方法。hello thread = new hello();运行这句话的时候会调用hello的构造方法,Thread.currentThread().getName()是获得调用这个方法的线程的名字,在main线程中调用的当然是main了,而this.getName()这个方法是获取当前hello对象的名字,只是单纯的方法的调用。因为没有重写这个方法所以调用的是父类Thread(把这个对象当作是普通的对象)中的方法。
1
2
3
4
5
6
7
|
this
.getName()-->
public
final
String getName() {
return
String.valueOf(name);
}-->所以最终是输出name的值,因为你在hello的构造方法中没有显式调用父类的所以调用的是默认无参的
public
Thread() {
init(
null
,
null
,
"Thread-"
+ nextThreadNum(),
0
);
}-->最终的名字就是这个
"Thread-"
+ nextThreadNum()-->
private
static
synchronized
int
nextThreadNum() {
return
threadInitNumber++;
}-->
private
static
int
threadInitNumber;因为是第一次调用nextThreadNum() 方法所以返回值为
0
-->
this
.getName()=Thread-
0
|
===================================================================
Thread中的setName方法
private char name[];
public final void setName(String name) { //final类型,不能覆盖了
checkAccess();
this.name = name.toCharArray(); //name是数组形式
}
public final String getName() { // getName也是final类型,不能覆盖
return String.valueOf(name); //name是数组形式
}
=============================================================================
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
/**
* Initializes a Thread with the current AccessControlContext.
* @see #init(ThreadGroup,Runnable,String,long,AccessControlContext)
*/
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
init(g, target, name, stackSize, null);
}
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc) {
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name.toCharArray();
Thread parent = currentThread();
SecurityManager security = System.getSecurityManager();
if (g == null) {
/* Determine if it's an applet or not */
/* If there is a security manager, ask the security manager
what to do. */
if (security != null) {
g = security.getThreadGroup();
}
/* If the security doesn't have a strong opinion of the matter
use the parent thread group. */
if (g == null) {
g = parent.getThreadGroup();
}
}
/* checkAccess regardless of whether or not threadgroup is
explicitly passed in. */
g.checkAccess();
/*
* Do we have the required permissions?
*/
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
g.addUnstarted();
this.group = g;
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext =
acc != null ? acc : AccessController.getContext();
this.target = target;
setPriority(priority);
if (parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
/* Set thread ID */
tid = nextThreadID();
}
public final String getName() { // getName也是final类型,不能覆盖
return String.valueOf(name); //name是数组形式
}
CountOperate ce = new CountOperate(); //创建的线程对象 0
Thread td = new Thread(ce); //又封装了一个线程对象1
td.setName("A");
td.start();
this.getName和Thread.currentThread().getName()不一样。currentThread().getName()获取当前调用该方法的线程的名称;
this.getName当前对象的名称
Thread子类的getName()方法当然是从Thread中继承过来的,由于Thread中的getName方法是final类型的,所以Thread子类不能对该方法进行覆盖。this.getName()中this表示本类,super表示父类,一般this可以忽略,只是某些时候如果子类覆盖了父类中方法,用this.getName(),super.getName()代码上更清晰。这里不能覆盖this.getName(),super.getName(),getName()都一样。总结:
supr和this只有子类继承父类,并且父类掉用子类的时候才能使用,否则其他情况下supr,this一样,用不用无所谓
之所以super.getName()与super.getName()一样,是因为,第一次创建对象CountOperate ce = new CountOperate(); 的时候,生成了一个线程名字,
这个线程对象和下面的Thread不是一回事,它继承的也不是td所在的Thread,所以td所在的Thread对 super.getName()没有任何影响。
ce对this.getName()或super.getName()才有直接且真正的影响,构造函数在前,set在后,所以构造函数中的this.getName()不受ce.setName()影响。
ce.start();之后,自动调用run()方法,run()方法中的this.getName()就会受到影响了。