今天在研究学习ThreaLocal的时候发现一个问题。如下:
我在main方法中新建了两个线程并调用他们的run()方法,并在run()方法里打印当前的线程信息,发现自始至终都只有一个main线程比较疑惑,随后我把run()方法改为start()方法发现这个问题不见了,让我一下意识到start()和run()之间是存在区别的,但是我之前并没有注意到这两个方法的区别。
先来看下代码吧
public class App {
public static void main(String[] args)throws Exception {
User user1 = new User(1, "张三");
User user2 = new User(2, "李四");
User user3 = new User(3, "王五");
UserHolder.set(user3);
MyThread t1 = new MyThread(user1);
MyThread t2 = new MyThread(user2);
t1.run();
t2.run();
System.out.println(Thread.currentThread().getName() + "------" + UserHolder.get());
}
}
class MyThread implements Runnable {
private User user;
public MyThread(User user) {
this.user = user;
}
public void run() {
System.out.println(Thread.currentThread().getName() + "------" + UserHolder.get());
UserHolder.set(user);
System.out.println(Thread.currentThread().getName() + "------" + UserHolder.get());
}
}
输出结果是这样:
main------User{id=3, uername='王五'}
main------User{id=1, uername='张三'}
main------User{id=1, uername='张三'}
main------User{id=2, uername='李四'}
main------User{id=2, uername='李四'}
注意到线程名称每次打印出来的都是main,这很疑惑,我明明在线程的run()方法里打印的当前线程名称怎么都是main呢?之后我修改代码为如下
public class App {
public static void main(String[] args)throws Exception {
User user1 = new User(1, "张三");
User user2 = new User(2, "李四");
User user3 = new User(3, "王五");
UserHolder.set(user3);
MyThread t1 = new MyThread(user1);
MyThread t2 = new MyThread(user2);
// t1.run();
// t2.run();
Thread thread1 = new Thread(t1);
Thread thread2 = new Thread(t2);
thread1.start();
thread2.start();
System.out.println(Thread.currentThread().getName() + "------" + UserHolder.get());
}
}
此时运行结果为下面这样
main------User{id=3, uername='王五'}
Thread-0------null
Thread-0------User{id=1, uername='张三'}
Thread-1------null
Thread-1------User{id=2, uername='李四'}
这下总是我想想的样子了,但是这是什么原因呢?很容易发现这两个方法是存在区别的,自己看不出来就去搜索了下,网上说的千篇一律就是这样子的。
1.用 start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的 start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法,这里方法 run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。
2.run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。
到此心中的疑惑得到了解答,满足了自己的好奇心,对于ThreadLocal也有了一定的认识。学到的新东西很满足。哈哈哈哈