为什么java线程在独立代码之后执行



我是java的新手,正在学习多线程。我写了以下代码。

class BackgroundTask implements Runnable {
private int counter = 0;
public int getCounter() {
return counter;
}
public void setCounter(int counter) {
this.counter = counter;
}
@Override
public void run() {
System.out.println("Thread started");
while (true) {
this.setCounter(this.getCounter() + 1);
}
}
}
public class Main {
public static void main(String[] args) {
BackgroundTask bgTask = new BackgroundTask();
Thread bgCount = new Thread(bgTask);
try {

bgCount.start();
System.out.println("counter in background is running");

bgCount.interrupt();
System.out.println(bgTask.getCounter());
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}

代码输出:

counter in background is running
0
Thread started

Q.1为什么bgCount.start()在print语句之后执行,而在它之前写入?

Q.2为什么线程在调用getCounter()方法后启动?

编辑:感谢大家提供的所有很酷的答案,现在我明白了线程的概念。

当您在两个不同的线程中执行操作时,除非强制进行某种同步,否则它们是不同步的。一个线程可能首先执行,另一个线程也可能以不可预测的方式交错。这就是线程的点。

说明

Q.1为什么bgCount.start()在print语句之后执行,而在它之前写入?

事实并非如此,这是一个错误的结论。start()正是在您编写它的时候执行的。这并不一定意味着线程立即启动。操作系统调度程序确定何时启动线程。你得到的唯一保证是它最终会开始,所以也许现在,也许一个小时后,也许明年。显然,在实践中,它通常是即时的。但这并不意味着它将作为下一件事来执行。

Q.2为什么线程在调用getCounter()方法后启动?如前所述,由操作系统调度程序决定。你只是运气不好。说真的,你无法控制这件事,也不应该对此做任何假设。


多线程

如果您有多个线程,并且它们有一系列操作要执行,则操作系统调度程序可以完全自由地决定如何交错操作。这也意味着不交错任何内容也是有效的。

让我们看一个线程AB的示例,它们各有2个操作要执行。以下执行顺序都是调度器的有效结果:

A.1
A.2
B.1
B.2
A.1
B.1
A.2
B.2
A.1
B.1
B.2
A.2
B.1
B.2
A.1
A.2
B.1
A.1
B.2
A.2
B.1
A.1
A.2
B.2

因此,您不能对线程何时启动做出任何假设,尤其不能对其他线程执行顺序操作做出任何假设。它可能是完全交错的,可能是顺序的,可能部分交错的,一切都可能发生。

如果您想控制该机制,正确的工具是同步。这样,你就可以判断出你想等待某件事首先在另一个线程中发生,然后再继续。上面代码的一个非常简单的例子是,等待bgCount完全完成后再继续打印计数。您可以使用join():

bgCount.start();
System.out.println("counter in background is running");

bgCount.join(); // waiting until down
System.out.println(bgTask.getCounter());

然而,如果你这样做,你首先就违背了拥有线程的目的。如果完全阻塞另一个线程并等待,那么并行计算就没有任何好处。然后,它基本上就像以普通的顺序方式执行某个东西一样。

最新更新