Thread.currentThread()与this获得当前线程引用的区别

原文链接:点击打开链接点击打开链接

在自定义线程类时,如果线程类是继承java.lang.Thread的话,那么线程类就可以使用this关键字去调用继承自父类Thread的方法,this就是当前的对象。

另一方面,Thread.currentThread()可以获取当前线程的引用,一般都是在没有线程对象又需要获得线程信息时通过Thread.currentThread()获取当前代码段所在线程的引用。

尽管this与Thread.currentThread() 都可以获取到Thread的引用,但是在某种情况下获取到的引用是有差别的,下面进行举例说明

[java]  view plain  copy
  1. public class MyThread extends Thread {  
  2.       
  3.     public MyThread(){  
  4.           
  5.         System.out.println("------" + "构造函数开始" + "------");  
  6.         System.out.println("Thread.currentThread().getName() = " + Thread.currentThread().getName());  
  7.         System.out.println("Thread.currentThread().isAlive() = " + Thread.currentThread().isAlive());  
  8.         System.out.println("this.getName() = " + this.getName());  
  9.         System.out.println("this.isAlive() = " + this.isAlive());  
  10.         System.out.println("------" + "构造函数结束" + "------");  
  11.           
  12.     }  
  13.       
  14.     @Override  
  15.     public void run(){  
  16.           
  17.         Thread testThread = Thread.currentThread();  
  18.           
  19.         System.out.println("------" + "run()开始" + "------");  
  20.         System.out.println("Thread.currentThread().getName() = " + Thread.currentThread().getName());  
  21.         System.out.println("Thread.currentThread().isAlive() = " + Thread.currentThread().isAlive());  
  22.         System.out.println("this.getName() = " + this.getName());  
  23.         System.out.println("this.isAlive() = " + this.isAlive());  
  24.         System.out.println("Thread.currentThread() == this : " + (Thread.currentThread() == this));  
  25.         System.out.println("------" + "run()结束" + "------");  
  26.           
  27.     }  
  28.       
  29. }  

测试类:

[java]  view plain  copy
  1. public class Test {  
  2.     public static void main(String[] args){  
  3.           
  4.         MyThread myThread = new MyThread();  
  5.         myThread.setName("A");  
  6.         myThread.start();  
  7.           
  8.     }  
  9. }  

测试结果:

------构造函数开始------
Thread.currentThread().getName() = main
Thread.currentThread().isAlive() = true
this.getName() = Thread-0
this.isAlive() = false
------构造函数结束------
------run()开始------
Thread.currentThread().getName() = A
Thread.currentThread().isAlive() = true
this.getName() = A
this.isAlive() = true
Thread.currentThread() == this : true
------run()结束------


我们会发现this 与 Thread.currentThread()是同一个引用

先说构造方法中的代码结果

Thread.currentThread().getName() = main
Thread.currentThread().isAlive() = true


这个结果没什么好说的,实例化MyThread,调用MyThread构造方法是主线程main

this.getName() = Thread-0
this.isAlive() = false

现在,这个this是什么?MyThread的引用,是个线程类,但是这个线程类并没有设置名字,所以Thread默认给了一个Thread-0
默认名字的规则定义如下:


因为仅仅是运行构造方法,还未运行线程,所以this.isAlive() = false

之后是run()中的代码结果
Thread.currentThread().getName() = A
Thread.currentThread().isAlive() = true

当前线程名字为A,A是我们手动赋予的myThread.setName("A");,并且它是运行着的

this.getName() = A
this.isAlive() = true

因为,我们运行的线程就是MyThread的引用,而this也是MyThread的引用,所以打印结果与Thread.currentThread()相同,
并且Thread.currentThread() == this : true


当我们保持线程类不变,如下修改测试类:

[java]  view plain  copy
  1. public class Test {  
  2.     public static void main(String[] args){  
  3.           
  4.         MyThread myThread = new MyThread();  
  5.         // 将线程对象以构造参数的方式传递给Thread对象进行start()启动线程  
  6.         Thread newThread = new Thread(myThread);  
  7.         newThread.setName("A");  
  8.         newThread.start();  
  9.           
  10.     }  
  11. }  

测试结果如下:

------构造函数开始------
Thread.currentThread().getName() = main
Thread.currentThread().isAlive() = true
this.getName() = Thread-0
this.isAlive() = false
------构造函数结束------
------run()开始------
Thread.currentThread().getName() = A
Thread.currentThread().isAlive() = true
this.getName() = Thread-0
this.isAlive() = false
Thread.currentThread() == this : false
------run()结束------

会发现,我们会发现this 与 Thread.currentThread()不是同一个引用


将线程对象以构造参数的方式传递给Thread对象进行start()启动线程,我们直接启动的线程实际是newThread,而作为构造参数的myThread,赋给Thread类中的属性target,之后在Thread的run方法中调用target.run();

此时Thread.currentThread()是Thread的引用newThread, 而this依旧是MyThread的引用,所以是不一样的,打印的内容也不一样

一,存在的问题

  Thread.currentThread()是Thread的一个静态方法,用来获取当前线程对象的一个引用。 
  问题在于为什么不简单的用this来获取,而单独写了一个静态的currentThread()方法来获取当前线程呢?

二,一个小demo

  首先看一个小例子,该例子引用自知乎https://www.zhihu.com/question/20944522

    public class Demo {
        public static void main(String[] args) {
            MyThread mt = new MyThread();
            new Thread(mt).start();
            new Thread(mt, "Name1").start();
            new Thread(mt, "Name2").start();

            System.out.println(Thread.currentThread().getName()); // main主方法
    //      System.out.println(this.getName());                   // this获取不到线程对象
        }
    }

    class MyThread extends Thread {
        @Override
        public void run() {
            try {
                Thread.sleep(3000);
                Thread t = Thread.currentThread();
                System.out.println("当前线程名字:" + t.getName() + " 当前线程的优先级别为:"+ t.getPriority() + " ID:" + t.getId());
   //           System.out.println("当前线程名字:" + this.getName() + " 当前线程的优先级别为:" + this.getPriority() + " ID:"+ this.getId());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

上面这个例子的执行结果是:

main
当前线程名字:Thread-1 当前线程的优先级别为:5 ID:10
当前线程名字:Name1 当前线程的优先级别为:5 ID:11
当前线程名字:Name2 当前线程的优先级别为:5 ID:12
  • 1
  • 2
  • 3
  • 4

这个结果应该是没什么问题的,切换注释后(main中的注释切换后编译错误,这很好理解)执行的结果是:

main
当前线程名字:Thread-0 当前线程的优先级别为:5 ID:9
当前线程名字:Thread-0 当前线程的优先级别为:5 ID:9
当前线程名字:Thread-0 当前线程的优先级别为:5 ID:9
  • 1
  • 2
  • 3
  • 4

  这个结果如何解释呢?为什么输出的都一样呢? 
  其实这时的this并不是new Thread(mt),new Thread(mt, “Name1”)以及new Thread(mt, “Name2”),而是mt,所以输出一致,都是mt的名称和id。

三,总结

  Thread提供静态方法currentThread()来供我们调用,既可以避免this无法获取到main线程的问题,又可以避免this无法获取到Thread t2=new Thread(Thread t)来开启的线程的问题,可以说currentThread方法可以在所有场合获取到正确的当前线程。当然,具体底层实现是由C语言实现的,不需要深究。




猜你喜欢

转载自blog.csdn.net/wang907553141/article/details/80728251