前提

    最近在学习多线程这一部分的内容,学习过程遇到不太理解的方法,特此总结一下。

如果从开始,先了解一下如何创建线程《Thread VS Runnable》

start()和run()

public class MyThread extends Thread {

public MyThread() {
System.out.println("构造方法的打印:" + Thread.currentThread().getName());
}

@Override
public void run() {
System.out.println("run方法的打印:" + Thread.currentThread().getName());
}

//region start VS run
public static void main(String[] args) {
System.out.println("当前线程名称:"+Thread.currentThread().getName());
MyThread myThread = new MyThread();
// myThread.start();
// myThread.run();
}
//endregion
}

1、start()

【多线程】——start() vs run() 以及this vs Thread.currentThread()_多线程

2、run()

【多线程】——start() vs run() 以及this vs Thread.currentThread()_主线程_02

start()

用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法,这里方法 run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。

run()

run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。

start VS run

调用start方法方可启动线程,而run方法只是thread的一个普通方法调用,还是在主线程里执行。这两个方法应该都比较熟悉,把需要并行处理的代码放在run()方法中,start()方法启动线程将自动调用 run()方法,这是由jvm的内存机制规定的。并且run()方法必须是public访问权限,返回值类型为void.

sleep()

是指让当前“正在执行的线程休眠”即指this.currentThread()返回的线程。

结合start()和run()使用sleep()方法感受一下什么是正在执行的线程休眠。

public class MyThread1 extends Thread {
@Override
public void run() {
try {
System.out.println("run threadName:" + this.currentThread().getName() + " begin="+System.currentTimeMillis());
Thread.sleep(2000);
System.out.println("run threadName:" + this.currentThread().getName() + " end ="+System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
}
}
//region  sleep 中start和run的区别
public static void main(String[] args) {
MyThread1 myThread1 = new MyThread1();
System.out.println("run currentName:" + Thread.currentThread().getName());
System.out.println("begin=" + Instant.now().toEpochMilli());
/*
1、使用start,休眠的是Thread-0线程,因为start开始一个新的线程,而sleep是让正在执行的线程休眠
run currentName:main
begin=1524536698550
end =1524536698550
run threadName:Thread-0 begin=1524536698553
run threadName:Thread-0 end =1524536700565
*/
// myThread1.start();

/*
2、使用run和普通方法一样,直接调用run,还在主线程中执行,所有当前正在执行的线程是main,所以main线程休眠
run currentName:main
begin=1524536822192
run threadName:main begin=1524536822192
run threadName:main end =1524536824193
end =1524536824193
*/
// myThread1.run();
System.out.println("end =" + Instant.now().toEpochMilli());
}
//endregion

this vs Thread.currrentThread()

isAlive()判断当前线程是否正在活动。

public class CountOperate extends Thread {

public CountOperate() {
System.out.println("CountOperate--begin");
//Thread.currentThread.getName 是指当前这段代码执行的执行线程,初始化的是main线程在执行,所以this没有活动
System.out.println("Thread.currentThread.getName:" + Thread.currentThread().getName());
System.out.println("Thread.currentThread.isAlive:" + Thread.currentThread().isAlive());

this.setName("CountOperate");

//this.getName 当前对象
System.out.println("this.getName:" + this.getName());
System.out.println("this.isAlive:" + this.isAlive());
System.out.println("CountOperate---end");
}

@Override
public void run() {
System.out.println("run--begin");
//实际执行的是thread对象的run方法
System.out.println("Thread.currentThread.getName:" + Thread.currentThread().getName());
System.out.println("Thread.currentThread.isAlive:" + Thread.currentThread().isAlive());

//执行这段代码的线程实际是CountOperate
System.out.println("this.getName:" + this.getName());
System.out.println("this.isAlive:" + this.isAlive());
System.out.println("run---end");
}
}
//region this和Thread.currentThread()以及this.currentThread
public static void main(String[] args) {
CountOperate countOperate = new CountOperate();
Thread t1 = new Thread(countOperate);
System.out.println("main begin t1 isAlive:" + t1.isAlive());
t1.setName("t1");
t1.start();
System.out.println(Thread.currentThread().getName());
System.out.println("main end t1 isAlive:" + t1.isAlive());
}
//endregion

打印结果

【多线程】——start() vs run() 以及this vs Thread.currentThread()_主线程_03

观察this和Thread.currentThread的isAlive()竟然是一个true和一个false

    说明此时的this和Thread.currentThread()指向不是同一个线程实例
也就是说,this指向的还是new CountOperate()创建的那个线程实例即countOperate,而不是new Thread(countOperate)创建的那个实例即t1。

查看源代码可以知道: 

实际上new Thread(countOperate)会将countOperate应用的对象绑定到一个pravite变量target上,

在t1被执行的时候即t1.run()被调用的时候,它会调用target.run()方法,也就是说它是直接调用countOperate对象的run方法

再确切的说,

在run方法被执行的时候,this.getName()实际上返回的是target.getName()也就是countOperate.getName(),而Thread.currentThread().getName()实际上是t1.getName()。

简单来说就是 this指向countOperate 而  currentThread()指向 t1

Thread.currentThread()和this.currentThread()

在大部分情况下结果是相同的,都是调用Thread的静态方法currentThread()

若当前子类重写了父类的currentThread()方法

那么Thread.currentThread()和this.currentThread()返回的结果会不同。

总结

    刚刚开始学习多线程,有些概念非常的生疏,再加上线程的时候需要非常的小心,所以尽可能去尝试自己不理解的内容多熟悉一下。

     如有理解偏颇之处,还请各位大神指正,不胜感激!