多线程等待所有子线程执行完使用总结——wait()和notify(),join()方法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程等待所有子线程执行完使用总结——wait()和notify(),join()方法相关的知识,希望对你有一定的参考价值。
多线程等待所有子线程执行完使用总结(1)——wait()和notify(),join()方法
问题背景
我们在日常开发和学习过程中,经常会使用到多线程的场景,其中我们经常会碰到,我们代码需要等待某个或者多个线程执行完再开始执行,那么这种场景可以有多少方法实现呢?本文就对这个场景的解决方案进行初步的介绍。
问题分析
1、Object的wait()和notify()方法
等待(wait):一个线程因为执行某个操作所需的保护条件未满足而被暂停的过程。 通知(notify):一个线程更新了共享变量,使得其他线程需要的保护条件成立,唤醒了被暂停的线程的过程。 wait()方法的执行线程叫等待线程,notify()方法执行的线程叫通知线程。 demo代码如下:
package composer
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import java.lang.Thread.sleep
class TestWaitActivity : AppCompatActivity()
private val lockObject = Object()
companion object
const val TAG = "TestWaitActivity"
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test_wait)
Log.d(TAG, "onCreate begin")
val threadWait = WaitThread()
threadWait.start()
// 获取当前系统时间
val beginTime = System.currentTimeMillis()
synchronized(lockObject)
try
Log.d(TAG, "主线程开始等待")
lockObject.wait()
catch (e: InterruptedException)
e.printStackTrace()
Log.d(TAG, "耗时:" + (System.currentTimeMillis() - beginTime))
inner class WaitThread: Thread()
override fun run()
Log.d(TAG, "WaitThread run begin")
synchronized (lockObject)
try
Log.d(TAG, "WaitThread synchronized")
// 模拟耗时任务
sleep(3000)
lockObject.notify()
catch (e: InterruptedException)
e.printStackTrace();
运行结果如下: 运行结果分析: wait()方法可以使当前线程A马上失去对象锁并且沉睡,直到对象调用notify()唤醒该线程。此时持有对象锁的线程会先行执行完毕,然后再将对象锁交给沉睡的线程继续执行。
2、线程的join()方法
thread.join()把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,那么要等线程A执行完毕后,才会继续执行线程B。demo代码如下:
fun main()
val thread1 = Thread
run
println("i am thread1")
// 模拟耗时任务
Thread.sleep(2000)
println("i am thread1 sleep ok")
val thread2 = Thread
run
thread1.join()
println("i am thread2")
thread1.start()
thread2.start()
运行结果如下: 运行结果分析: 线程2的run()方法中调用thread1.join(),这个位置会等thread1执行完才会继续去执行线程2中的代码。 这里也可以看下Thread类join的源码也比较容易理解: (1)java.lang.Thread#join()
/**
* Waits for this thread to die.
*
* <p> An invocation of this method behaves in exactly the same
* way as the invocation
*
* <blockquote>
* @linkplain #join(long) join@code (0)
* </blockquote>
*
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* <i>interrupted status</i> of the current thread is
* cleared when this exception is thrown.
*/
public final void join() throws InterruptedException
join(0);
(2)java.lang.Thread#join(long)
public final void join(long millis)
throws InterruptedException
synchronized(lock)
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0)
throw new IllegalArgumentException("timeout value is negative");
if (millis == 0)
while (isAlive())
lock.wait(0);
else
while (isAlive())
long delay = millis - now;
if (delay <= 0)
break;
// 通过Object对象的wait方法,进行一个延迟时间的等待
lock.wait(delay);
now = System.currentTimeMillis() - base;
问题总结
本文主要介绍了等待线程结束再执行的两个方案,(1)Object的wait()和notify()方法,(2)线程的join()方法,后面会继续介绍CountDownLatch类、CyclicBarrier类和自定义个一个原子类型计数器的方法,有兴趣的同学可以进一步深入研究。
以上是关于多线程等待所有子线程执行完使用总结——wait()和notify(),join()方法的主要内容,如果未能解决你的问题,请参考以下文章
多线程等待所有子线程执行完使用总结——CyclicBarrier使用和源码初步分析