Java 启动线程 —— start和run的区别

  在学习 Java 线程部分内容时,对于 Java 启动线程时,经常会混淆两个方法—— start() 方法和 run() 方法。起初可能不会感觉到这两个方法有什么区别,因为它们都会执行 run() 方法中的代码,但是执行 run() 方法中代码的线程是不同的,直接调用 run() 方法是由主线程执行的,而调用 start() 方法才是新建了一个线程,由这个线程执行 run() 方法中的代码。

  接下来演示一下 start() 方法和 run() 方法的执行结果,通过这个结果再来体会 start() 和 run() 的区别。

运行实例

  创建两个线程 thread1 和 thread2,每个线程的 run() 方法是输出5次当前的线程名。
  其中创建线程时使用的是Thread(Runnable target, String name)这个构造方法,该构造方法会为创建的线程起一个名字 name。
  在 run() 方法输出语句中,Thread.currentThread() 是获取当前正在执行的线程,getName() 是获取线程的名字。

// 创建线程thread1和thread2
Thread thread1 = new Thread(new Runnable() {
    
    
	public void run() {
    
    
		for (int i = 0; i < 5; i++)
			System.out.println(Thread.currentThread().getName() + "--" + i);
	}
}, "thread1");
Thread thread2 = new Thread(new Runnable() {
    
    
	public void run() {
    
    
		for (int i = 0; i < 5; i++)
			System.out.println(Thread.currentThread().getName() + "++" + i);
	}
}, "thread2");

我们来看看调用 start() 方法和 run() 方法的实际输出情况。

start() 方法

public void startMethod() {
    
    
	thread1.start();
	thread2.start();
}
public static void main(String[] args) {
    
    
	MethodDifferences md = new MethodDifferences();
	md.startMethod();
}

在这里插入图片描述
  可以看到 thread1 和 thread2 的 run() 方法交替执行,达到了我们希望的多线程并发执行的效果。

run() 方法

public void runMethod() {
    
    
	thread1.run();
	thread2.run();
}
public static void main(String[] args) {
    
    
	MethodDifferences md = new MethodDifferences();
	md.runMethod();
}

在这里插入图片描述
  可以看到当前执行的线程不是 thread1 和 thread2,而是 main 线程,而且是先执行了 thread1 的 run(),在执行 thread2 的 run(),并不是并发执行,而是按照程序顺序依次执行。

补充

  在 Java 的程序中使用new Thread() 只是创建了一个 Thread 类的对象,此时和普通的对象没有任何区别,并没有因为 Java 程序中创建一个 Thread 对象就在操作系统中创建一个线程,真正在操作系统中创建了一个线程是 Java 中调用 start() 方法。

  run() 方法就是一个普通方法,直接使用 run(),其实就是之前使用的方法调用,并没有在操作系统层面创建新的线程,而是由调用 Thread 对象 run() 方法的主线程执行,在上面 run() 的实例中也有体现,当前执行的线程名是 main,而不是 thread1 或者 thread2。

  start() 方法其实也是 Java 中的一个普通方法,查看 start() 方法的源码,可以看到在 start() 源码中调用了private native void start0();,start0() 方法 是一个 native 方法,它的实现是用 C++ 实现的,在 start0() 方法中调用到了 cpppthread_create() 方法,而这个方法才是在操作系统中创建了一个线程。
  另外,在 start() 方法中并没有看到任何与调用 run() 方法有关的代码,在 start() 方法的注释中有一段话,说明了是在 JVM 中调用了 run() 方法。

 /**
  * Causes this thread to begin execution; the Java Virtual Machine
  * calls the <code>run</code> method of this thread.
  * /

  理解这些,再回来看 run() 和 start() 的区别就比较好理解了,调用 run() 方法是没有创建新的线程,而是当前线程调用 run() 方法,而 start() 方法会调用 start0() 方法来间接调用了 cpppthread_create() 方法最终在操作系统中真正创建一个线程,由这个线程来执行 run() 方法。

猜你喜欢

转载自blog.csdn.net/qq_40395874/article/details/115233455