Java 线程如何知道前面有一个连接方法

Java 线程如何知道前面有一个连接方法,java,multithreading,pthread-join,Java,Multithreading,Pthread Join,下面是我的示例代码,当调用我的a.start()时,它应该创建一个线程并立即打印“Run”。但为什么打印后被称为“开始”20次 线程“a”如何决定它不必立即调用run() public class JoinTest implements Runnable { public static void main(String[] args) throws InterruptedException { Thread a = new Thread(new JoinTest());

下面是我的示例代码,当调用我的
a.start()
时,它应该创建一个线程并立即打印“Run”。但为什么打印后被称为“开始”20次

线程“a”如何决定它不必立即调用
run()

public class JoinTest implements Runnable {

    public static void main(String[] args) throws InterruptedException {
        Thread a = new Thread(new JoinTest());
        a.start();

        for (int i = 0; i < 20; i++) {
            System.out.print("Begin");
        }
        Thread.sleep(1000);

        a.join();
        System.out.print("\nEnd");
    }

    public void run() {
        System.out.print("\nRun");
    }
}
我对线程的行为有点困惑


在我看来,
“run”
应该在
“begin”
之前打印,因为它是在调用
join()
方法之前打印的,在调用join方法时,名为thread“a”的方法必须已完成其执行,此时调用join肯定是无用的。

您启动线程,然后立即进行一些打印,然后睡觉。查看您的代码时,我实际上希望看到
Begin
Run
之前,因为线程是在后台启动的,与主线程同时进行工作。此外,
print
方法是同步的,因此您可以在循环中重复获取该锁,从而减少第二个线程插入的机会

我已使用
线程尝试了您的代码。睡眠
已消除,无论是否使用
加入
调用。这两种情况下的行为都是相同的:
Run
大部分时间在末尾出现,偶尔会在
Begin
单词之间交错出现。一切都完全符合使用同步块的简单并发模型的预期

下面是代码的一个细微变化,它可以可靠地打印
Run
,而不管您是否调用
join
方法。所有的改变都是
sleep
调用的位置

public class JoinTest implements Runnable
{
  public static void main(String[] args) throws InterruptedException {
    Thread a = new Thread(new JoinTest());
    a.start();

    Thread.sleep(1000);
    for (int i = 0; i < 20; i++) {
      System.out.print("Begin");
    }

    a.join();
    System.out.print("\nEnd");
  }

  public void run() {
    System.out.print("\nRun");
  }
}
公共类JoinTest实现可运行
{
公共静态void main(字符串[]args)引发InterruptedException{
线程a=新线程(新JoinTest());
a、 start();
睡眠(1000);
对于(int i=0;i<20;i++){
系统输出打印(“开始”);
}
a、 join();
系统输出打印(“\nEnd”);
}
公开募捐{
系统输出打印(“\n运行”);
}
}

启动线程,然后立即进行打印,然后进入睡眠状态。查看您的代码时,我实际上希望看到
Begin
Run
之前,因为线程是在后台启动的,与主线程同时进行工作。此外,
print
方法是同步的,因此您可以在循环中重复获取该锁,从而减少第二个线程插入的机会

我已使用
线程尝试了您的代码。睡眠
已消除,无论是否使用
加入
调用。这两种情况下的行为都是相同的:
Run
大部分时间在末尾出现,偶尔会在
Begin
单词之间交错出现。一切都完全符合使用同步块的简单并发模型的预期

下面是代码的一个细微变化,它可以可靠地打印
Run
,而不管您是否调用
join
方法。所有的改变都是
sleep
调用的位置

public class JoinTest implements Runnable
{
  public static void main(String[] args) throws InterruptedException {
    Thread a = new Thread(new JoinTest());
    a.start();

    Thread.sleep(1000);
    for (int i = 0; i < 20; i++) {
      System.out.print("Begin");
    }

    a.join();
    System.out.print("\nEnd");
  }

  public void run() {
    System.out.print("\nRun");
  }
}
公共类JoinTest实现可运行
{
公共静态void main(字符串[]args)引发InterruptedException{
线程a=新线程(新JoinTest());
a、 start();
睡眠(1000);
对于(int i=0;i<20;i++){
系统输出打印(“开始”);
}
a、 join();
系统输出打印(“\nEnd”);
}
公开募捐{
系统输出打印(“\n运行”);
}
}
在线程上调用
start()
不一定会立即触发其
run()
方法的执行。您的线程被标记为已启动,但主线程在
for
循环中继续执行。一旦主线程到达
sleep()
语句,JVM就会切换到您的线程。

在线程上调用
start()
不一定会立即触发其
run()
方法的执行。您的线程被标记为已启动,但主线程在
for
循环中继续执行。然后,当主线程到达
sleep()
语句时,JVM将切换到您的线程。

方法调用线程的
run()
方法,尽管这需要一点时间,这可能足以让部分或所有“Begin”循环完成。当我在我的机器上运行时,“运行”输出出现在第一个和第二个“开始”之间。尝试使用时间戳输出,以便查看机器执行每个命令所需的时间:

public class JoinTest implements Runnable {

    public static void main(String[] args) throws InterruptedException {
        Thread a = new Thread(new JoinTest());
        a.start();

        for (int i = 0; i < 20; i++) {
            System.out.println("Begin " + System.nanoTime());
        }
        Thread.sleep(1000);

        a.join();
        System.out.println("End " + System.nanoTime());
    }

    public void run() {
        System.out.println("Run " + System.nanoTime());
    }
}
公共类JoinTest实现可运行{
公共静态void main(字符串[]args)引发InterruptedException{
线程a=新线程(新JoinTest());
a、 start();
对于(int i=0;i<20;i++){
System.out.println(“Begin”+System.nanoTime());
}
睡眠(1000);
a、 join();
System.out.println(“End”+System.nanoTime());
}
公开募捐{
System.out.println(“Run”+System.nanoTime());
}
}
此时调用
a.join()
可以确保在“End”之前始终看到“Run”输出,因为join()

方法调用线程的
Run()
方法,尽管这需要一点时间,这可能只够完成部分或全部“Begin”循环。当我在我的机器上运行时,“运行”输出出现在第一个和第二个“开始”之间。尝试使用时间戳输出,以便查看机器执行每个命令所需的时间:

public class JoinTest implements Runnable {

    public static void main(String[] args) throws InterruptedException {
        Thread a = new Thread(new JoinTest());
        a.start();

        for (int i = 0; i < 20; i++) {
            System.out.println("Begin " + System.nanoTime());
        }
        Thread.sleep(1000);

        a.join();
        System.out.println("End " + System.nanoTime());
    }

    public void run() {
        System.out.println("Run " + System.nanoTime());
    }
}
公共类JoinTest实现可运行{
公共静态void main(字符串[]args)引发InterruptedException{
线程a=新线程(新JoinTest());
a、 start();
对于(int i=0;i<20;i++){
System.out.println(“Begin”+System.nanoTime());
}