今天在研究学习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也有了一定的认识。学到的新东西很满足。哈哈哈哈