在一个开源项目中,有一个录音功能,录音是在一个子线程中完成的,当调用停止录音时,执行的函数如下:
public void stopRecordThread() {
if (recordThread != null) {
try {
recordThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
recordThread = null;
}
}
查看了JDK文档,join()函数的功能是:等待该线程终止。如上代码,我们调用录音线程的join函数,则是等待录音线程终止,也就是说,如果录音线程没执行完,stopRecord()函数就一直等在那里,是一个阻塞状态,写个示例代码演示如下:
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(Main::printInfo, "Thread");
thread.start();
printInfo();
}
public static void printInfo() {
try {
String name = Thread.currentThread().getName();
for (int i = 1; i <= 5; i++) {
System.out.println(name + " " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
这里有两个线程都调用了printInfo函数,一个是子线程,一个是主线程,printInfo函数的功能是打印5条信息,每条信息打印了线程名称和序号,每打印一条信息后就睡眠1秒钟,执行效果如下:
main 1
Thread 1
Thread 2
main 2
Thread 3
main 3
main 4
Thread 4
main 5
Thread 5
可以看到两个线程同时进行,如果我们希望子线程执行结束之后,再来执行主线程,只需要调用子线程的join函数即可实现,代码如下:
public static void main(String[] args) throws InterruptedException {
Thread threadA = new Thread(Main::printInfo, "Thread");
threadA.start();
threadA.join();
printInfo();
}
执行效果如下:
Thread 1
Thread 2
Thread 3
Thread 4
Thread 5
main 1
main 2
main 3
main 4
main 5
可以看到,调用了join()函数后,主线程就被阻塞了,不再往下执行,直到子线程执行结束后再往下执行。
回到文章的开头,一个录音线程,在调用录音Api的停止函数后,系统就不再给出录音数据了,但是录音线程可能还在写录音数据呢,所以要等录音线程执行完毕,不能直接中止录音线程,所以调用了join函数来实现。
后续:子线程执行完之后,子线程自己不就结束了吗?为什么需要调用一个join去把自己阻塞了呢?而且我们看到它调用join()的后面也没写别的代码。我猜啊,这个stopRecordThread()函数是一个回调函数,在别处调用这个函数,则在别处自然就会阻塞住了,所以阻塞之后做了什么就要看是什么地方调用了这个函数。我在这个函数上打印了一下线程名称,发现调用stopRecordThread()函数的函数也是在子线程上运行的,所以虽然阻塞了,但阻塞的是一个子线程,所以不用担心主线程。