乐趣区

关于java:ThreadcurrentThread与this的区别以及superrun的作用

一 Thread.currentThread() 与 this
本文探讨 Thread.currentThread() 与 this 不一样的状况。
在将线程对象以结构参数的形式传递给 Thread 对象进行 start() 启动时,Thread.currentThread() 与 this 的取值是不一样的。
代码:

package springboot.myrunable;

/**

  • @author liuhongya328
    *
    */

public class CountOperate extends Thread {

/**
 * 构造方法
 */
public CountOperate() {System.out.println("count-----begin");
    System.out.println("Thread.currentThread().getName()=" + Thread.currentThread().getName());
    System.out.println("Thread.currentThread().isAlive()=" + Thread.currentThread().isAlive());
    System.out.println("this.getName()=" + this.getName());
    System.out.println("this.isAlive()=" + this.isAlive());
    System.out.println("count-----end");
}

@Override
public void run() {System.out.println("run-----begin");
    System.out.println("Thread.currentThread().getName()=" + Thread.currentThread().getName());
    System.out.println("Thread.currentThread().isAlive()=" + Thread.currentThread().isAlive());
    System.out.println("this.getName()=" + this.getName());
    System.out.println("this.isAlive()=" + this.isAlive());
    System.out.println("run-----end");
}

}

测试类:

package springboot.myrunable;

/**

  • @author liuhongya328
    *
    */

public class TestThread {

/**
 * @param args
 */
public static void main(String[] args) {CountOperate cc = new CountOperate();
    Thread t1 = new Thread(cc);
    System.out.println("main begin t1 isalive="+t1.isAlive());
    t1.setName("A");
    t1.start();
    System.out.println("main end t1 isalive="+t1.isAlive());
}

}

运行后果:

count—–begin
Thread.currentThread().getName()=main
Thread.currentThread().isAlive()=true
this.getName()=Thread-0
this.isAlive()=false
count—–end
main begin t1 isalive=false
main end t1 isalive=true
run—–begin
Thread.currentThread().getName()=A
Thread.currentThread().isAlive()=true
this.getName()=Thread-0
this.isAlive()=false
run—–end

阐明:
1. 先看 Test 类
public static void main(String[] args) {
//main 函数过程开始 -name 为 main

// 创立了一个 cc 的线程,线程为新建状态。线程名为 Thread0
CountOperate cc = new CountOperate();
// 创立了一个 t1 的线程,线程为新建状态。线程名为 Thread1
Thread t1 = new Thread(cc);
System.out.println("main begin t1 isalive="+t1.isAlive());
// 将 Thread1 的名字改为 A
t1.setName("A");
//Thread1(A)启动,线程状态变为就绪
t1.start();
System.out.println("main end t1 isalive="+t1.isAlive());

}

2. 再看实现类

/**

 * 构造方法
 */
public CountOperate() {System.out.println("count-----begin");
    // 构造方法是 main 办法在执行
    System.out.println("Thread.currentThread().getName()=" + Thread.currentThread().getName());
    System.out.println("Thread.currentThread().isAlive()=" + Thread.currentThread().isAlive());
    // 以后线程的 name, 在 new CountOperate() 的时候曾经创立了 cc 线程,name 为 Thread0
    System.out.println("this.getName()=" + this.getName());
    System.out.println("this.isAlive()=" + this.isAlive());
    System.out.println("count-----end");
}


@Override
public void run() {System.out.println("run-----begin");
    //run 办法是 t1 办法在执行,t1.getName() 为 Thread1(A) 的名称
    System.out.println("Thread.currentThread().getName()=" + Thread.currentThread().getName());
    System.out.println("Thread.currentThread().isAlive()=" + Thread.currentThread().isAlive());
    

// public Thread(Runnable target) {
// init(null, target, “Thread-” + nextThreadNum(), 0);
// }

    // 下面是 t1 的构造函数,传入的对象实际上是指向 cc, 所以 this.getName() 是 cc 的 name-->Thread0
    System.out.println("this.getName()=" + this.getName());
    System.out.println("this.isAlive()=" + this.isAlive());

    // 退出这个可能会让了解更好点。System.out.println("this.currentThread().getName()=" + this.currentThread().getName());
    
    System.out.println("run-----end");
}

正文很具体,欢送交换!

二 super.run();
首先,咱们来看一下 JDK 的 Thread 源码

private Runnable target;
public void run() {

if (target != null) {target.run();  
}  

}

代码 1:

new Thread(new Runnable() {

@Override  
public void run() {System.out.println("Run of Runnable");  
}  

}) {

public void run() {System.out.println("Run of Thread");  
}  

}.start();

代码 2:

new Thread(new Runnable() {

@Override  
public void run() {System.out.println("Run of Runnable");  
}  

}) {

public void run() {System.out.println("Run of Thread");  
    super.run();}  

}.start();

在 run() 办法中,首先会查看 target 是否为空,如果不是,则执行该 target 的 run() 办法。

那么,对于下面两段代码的执行,也就分明了。

在第一个代码段 1 中,重写了 Thread 的 run() 办法,同时传入了一个 Runnable 对象,该对象也实现了 run() 办法。该 Thread 对象调用 start() 办法后,会执行该对象重写的 run() 办法,其输入后果也就是 Run of Thread,输入完后,run() 办法返回,该线程对象的生命周期也就完结了。

在第二个代码段 2 中,同样也重写了 Thread 的 run() 办法,同时传入了一个 Runnable 对象,实现了 run() 办法。惟一不同的是,在 Thread 重写的 run 办法中,在打印输出后,还执行了 super.run(),这就有意思了。

首先,该线程启动运行后,执行其重写的 run() 办法,输入 Run of Thread。

接下来调用 super.run(),也就是调用超类的 run() 办法,而该超类的 run() 办法,也就是 JDK 定义的 Thread 类的 run(),其执行如上代码段 3 所示;显然 target 不为空,这时候会调用该对象的 run() 办法,会输入 Run of Runnable.。

如果,下面的 Thread 并未重写 run() 办法,那么,执行的后果还是一样。首先会执行该 Thread 的 run() 办法,因为此时并未重写该办法,所以还是会调用 JDK 定以的 run() 办法,也就是下面的代码段 3,在该代码段中会判断 target 是否为空,显然不是,所以会调用 Runnable 对象实现的 run() 办法。

总结:

对于 Thread(Runnable target …),不论传入的 Target 是否为空,首先都会执行 Thread 本人的 run() 办法。

如果重写了该办法且该办法中没有 super.run(),那么是永远不会调用 Runnable 实现的 run() 办法;

如果没有重写该办法,则会去判断 target 是否为空,以此来决定调用 target 实现的 run() 办法;

如果重写了该办法,且该办法中有 super.run(),如代码 2,在执行完该语句之前的所有代码后,会判断 target 是否为空,以此来决定调用 target 实现的 run() 办法,执行完后,接着执行该语句之后的代码。

退出移动版