“Java join 线程”的版本间的差异

来自姬鸿昌的知识库
跳到导航 跳到搜索
 
(未显示同一用户的2个中间版本)
第6行: 第6行:
  
 
当所有的小问题都得到处理后,再调用主线程来进一步操作。
 
当所有的小问题都得到处理后,再调用主线程来进一步操作。
 +
 +
=== 代码 ===
 +
JoinThread.java<syntaxhighlight lang="java">
 +
public class JoinThread extends Thread {
 +
 +
    // 提供一个有参数的构造器,用于设置该线程的名字
 +
    public JoinThread(String name) {
 +
        super(name);
 +
    }
 +
 +
    // 重写 run() 方法,定义线程执行体
 +
    @Override
 +
    public void run() {
 +
        for (int i = 0; i < 100; i++) {
 +
            System.out.println(getName() + "  " + i);
 +
        }
 +
    }
 +
}
 +
</syntaxhighlight>Test.java<syntaxhighlight lang="java">
 +
public class Test {
 +
 +
    public static void main(String[] args) throws InterruptedException {
 +
 +
        // 启动子线程
 +
        new JoinThread("新线程").start();
 +
 +
        for(int i = 0; i< 100; i++) {
 +
 +
            if (i == 20) {
 +
                JoinThread jt = new JoinThread("被 Join 的线程");
 +
                jt.start();
 +
 +
                // main 线程调用了 jt 线程的 join 方法,main 线程必须等 jt 执行结束才会向下执行
 +
                jt.join();
 +
 +
            }// end if
 +
 +
            System.out.println(Thread.currentThread().getName() + "  " + i);
 +
 +
        } //end for
 +
 +
    }// end main
 +
}
 +
</syntaxhighlight><syntaxhighlight lang="console">
 +
……
 +
main  16
 +
新线程  93
 +
新线程  94
 +
新线程  95
 +
新线程  96
 +
main  17
 +
新线程  97
 +
新线程  98
 +
main  18
 +
新线程  99
 +
main  19
 +
被 Join 的线程  0
 +
被 Join 的线程  1
 +
被 Join 的线程  2
 +
被 Join 的线程  3
 +
……
 +
被 Join 的线程  96
 +
被 Join 的线程  97
 +
被 Join 的线程  98
 +
被 Join 的线程  99
 +
main  20
 +
main  21
 +
main  22
 +
……
 +
main  99
 +
</syntaxhighlight>上面程序中一共有3个线程,主方法开始时就启动了名为“新线程”的子线程,该子线程会和 main 线程并发执行。
 +
 +
当主线程的循环变量 i 等于 20 时,启动了名为“被 Join 的线程”的线程,该线程不会和 main 线程并发执行,main 线程必须等该线程执行结束后才可以向下执行。
 +
 +
在名为“被 Join 的线程”执行时,实际上只有2个子线程并发执行,而主线程处于等待状态。
 +
 +
从控制台输出可以看出,主线程执行到 i==20 时启动,并 join 了名为“被 Join 的线程”的线程,所以主线程将一直处于阻塞状态,直到名为“被 Join 的线程”的线程执行完成。
 +
 +
 +
 +
 +
=== join() 方法的3种重载形式 ===
 +
 +
# join():等待被 join 的线程执行完成
 +
# join(long millis):等待被 join 的线程的时间最长为 millis 毫秒。如果在 millis 毫秒内被 join 的线程还没有执行结束,则不再等待。
 +
# join(long millis, int nanos):等待被 join 的线程的时间最长为 millis 毫秒加 nanos 纳秒。
 +
 +
通常我们很少使用第3种形式的方法,原因有两个:程序对时间的精度无须精确到纳秒;计算机硬件、操作系统本身也无法精确到纳秒。

2023年2月20日 (一) 11:48的最新版本

Thread 提供了一个线程等待另一个线程完成的方法——join()方法。

当在某个程序执行流中调用其他线程的 join() 方法时,调用线程将被阻塞,知道被 join() 方法加入的 join 线程执行完为止。

join() 方法通常由使用线程的程序调用,以将大问题划分成许多小问题,每个小问题分配一个线程。

当所有的小问题都得到处理后,再调用主线程来进一步操作。

代码

JoinThread.java

public class JoinThread extends Thread {

    // 提供一个有参数的构造器,用于设置该线程的名字
    public JoinThread(String name) {
        super(name);
    }

    // 重写 run() 方法,定义线程执行体
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName() + "  " + i);
        }
    }
}

Test.java

public class Test {

    public static void main(String[] args) throws InterruptedException {

        // 启动子线程
        new JoinThread("新线程").start();

        for(int i = 0; i< 100; i++) {

            if (i == 20) {
                JoinThread jt = new JoinThread("被 Join 的线程");
                jt.start();

                // main 线程调用了 jt 线程的 join 方法,main 线程必须等 jt 执行结束才会向下执行
                jt.join();

            }// end if

            System.out.println(Thread.currentThread().getName() + "  " + i);

        } //end for

    }// end main
}
……
main  16
新线程  93
新线程  94
新线程  95
新线程  96
main  17
新线程  97
新线程  98
main  18
新线程  99
main  19
被 Join 的线程  0
被 Join 的线程  1
被 Join 的线程  2
被 Join 的线程  3
……
被 Join 的线程  96
被 Join 的线程  97
被 Join 的线程  98
被 Join 的线程  99
main  20
main  21
main  22
……
main  99

上面程序中一共有3个线程,主方法开始时就启动了名为“新线程”的子线程,该子线程会和 main 线程并发执行。

当主线程的循环变量 i 等于 20 时,启动了名为“被 Join 的线程”的线程,该线程不会和 main 线程并发执行,main 线程必须等该线程执行结束后才可以向下执行。

在名为“被 Join 的线程”执行时,实际上只有2个子线程并发执行,而主线程处于等待状态。

从控制台输出可以看出,主线程执行到 i==20 时启动,并 join 了名为“被 Join 的线程”的线程,所以主线程将一直处于阻塞状态,直到名为“被 Join 的线程”的线程执行完成。



join() 方法的3种重载形式

  1. join():等待被 join 的线程执行完成
  2. join(long millis):等待被 join 的线程的时间最长为 millis 毫秒。如果在 millis 毫秒内被 join 的线程还没有执行结束,则不再等待。
  3. join(long millis, int nanos):等待被 join 的线程的时间最长为 millis 毫秒加 nanos 纳秒。

通常我们很少使用第3种形式的方法,原因有两个:程序对时间的精度无须精确到纳秒;计算机硬件、操作系统本身也无法精确到纳秒。