十分钟搞定Java多线程-Java中Thread.start()和Thread.run()方法有什么不同

Java创建线程有两种方式:(这也是Java面试常被问到一个Java线程基础问题,不往下看你能回答出来吗?)

1) 通过继承 java.lang.Thread 类
2) 通过实现 java.lang.Runnable 接口。

Java启动线程通过调用java.lang.Thread的start()方法,而Thread实现了Runnable接口:

public class Thread implements Runnable

在方法内部调用了Runnable的run()方法来在单独的线程里执行run()方法:

@Override
public void run() {
   if (target != null) {
      target.run();
   }
}

现在问题来了,启动线程为什么不能直接调用run()方法而是调用start()方法呢

既然start()方法无论如何也会调用run()方法,那么我们直接调用run()方法应该与调用start()方法具有相同的效果吧?错!!

好吧,这也算是一个棘手的多线程问题,在Java面试中经常出现,实际上这个问题并不像看起来那么简单,特别是当你的Java多线程知识只是半桶水,那么你一定会在这个问题上栽跟头。

直接调用run()方法时,run()方法中的代码将在调用run方法的同一个线程中执行,JVM此时并不会创建一个新的线程,也就是说,程序只有主线程一个线程,不会有新的线程被创建,等待run()方法中的代码执行完了,才会顺序执行后面的代码。

当调用Thread.start()方法,JVM将会创建一个新的线程来执行run()方法里的代码,因此调用start()方法才会创建新的线程,在新线程执行run()方法里的代码的同时,后面的代码继续由主线程执行。

start()和run()方法之间的另一个关键区别,就是可以调用run()方法n多次,JVM不会抛出任务错误,但是不能在同一个线程实例里重复调用start()方法。

在同一个线程实例第一次调用start()方法,JVM会创建一个新的线程,但是第二次JVM会抛出java.lang.IllegalThreadStateException异常,因为这个线程已经存在,你不能再创建第二次,你可以中断这个线程,一旦它死了就会消失。

实际上,public void run()方法是在Runnable接口中定义的,并且由于java.lang.Thread类实现了Runnable接口,因此它会自动获取run方法。

接下来我们用代码来演示调用start()方法和调用run()方法的区别。

public class Thread1 extends Thread {

    public static void main(String args[]) {
        Thread t = new Thread() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " is executed the run() method");
            }
        };
        System.out.println(Thread.currentThread().getName() + " Calling the start() method of Thread");
        //调用start方法
        t.start();
        // 等待线程执行完
        try {
            t.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " Calling the run() method of Thread");
        //调用run方法
        t.run();
    }

}

执行结果:

main Calling the start() method of Thread
Thread-0 is executed the run() method
main Calling the run() method of Thread
main is executed the run() method

从代码执行的输出结果,配合下面的idea截图左下角的Debugger,可以清晰的看到main/主线程(在Java中执行main()方法的线程)调用start()方法,然后就创建了一个新的名称为Thread-0 的线程,并且run()方法也由该线程执行。但是如果我们直接调用run()方法,并没有创建新的线程来执行,而是由main/主线程来执行。

以上就是Java中的start()和run()方法之间的区别。 只要记住,在start()方法内部调用了run()方法,主要目的是创建一个新线程。 如果直接调用run()方法,则不会创建新线程,而是将在同一线程上执行run()。 这意味着你应该始终通过调用Java中的Thread.start()方法来启动线程。

发布了14 篇原创文章 · 获赞 2 · 访问量 1958

猜你喜欢

转载自blog.csdn.net/mcmoo/article/details/105758678