本文探讨了在Java编程语言中启动线程的两种方法——使用start()和直接调用run()方法之间的区别及其应用场景。
在Java编程语言中启动线程主要有两种方法:一种是继承Thread类;另一种则是实现Runnable接口来创建线程对象。由于Java不支持多重继承,因此推荐使用后者。
通过start()与run()这两种方式可以初始化或开始执行一个新线程:
- `start()` 方法用于开启一个新的独立运行的线程,并将该方法中的代码放入新的进程中去执行,这意味着当调用`start()`时,系统会创建一个全新的线程准备就绪等待CPU分配时间片来启动并进入run()方法中定义的任务。
- 相比之下,直接使用 `run()` 方法则更像是普通的方法调用。它不会生成额外的线程;相反,在当前执行流上下文中运行给定的代码块。这通常不是我们想要的效果,因为多线程编程的核心目标是并发地执行任务。
来看一个简单的例子来加深理解:
```java
public class Test {
public static void main(String[] args) {
Thread t = new Thread(){
public void run() {
pong();
}
};
// 假设这里使用的是run()
t.run();
System.out.println(ping);
}
static void pong() {
System.out.println(pong);
}
}
```
在这个例子中,如果调用`t.run()`而不是`t.start()`的话,那么先执行完线程中的代码(即打印pong),然后才会继续在主线程上输出“ping”。
但是,如果我们使用 `start()` 替换掉上述的 `run()`, 例如:
```java
public class Test {
public static void main(String[] args) {
Thread t = new Thread(){
public void run() {
pong();
}
};
// 改为调用 start()
t.start();
System.out.println(ping);
}
static void pong() {
System.out.println(pong);
}
}
```
那么程序输出结果将是“ping”后紧接着是pong, 因为`start()`方法会创建一个新线程,该线程立即准备运行(但并非马上执行),而main线程则继续向下执行。
关于 `start()` 和 `run()`, 它们在源码层面的区别在于:`start()` 方法被声明为同步的(synchronized),这意味着每次只能有一个线程调用它。这正是为什么它可以创建一个新的线程,而直接调用`run()`方法只是简单地执行代码块,并不会产生新的线程。
因此,在实际编程中选择使用哪种方式启动新线程应根据具体需求来决定。