Android -- 每日一问:如何处理线程同步的问题?

知识点

有可能很多人对插件并不了解,不过没关系,这个需求简单地说就是主线程要等待多个子线程全部完成工作后,才能继续执行。

说到多线程的同步问题,面试多的人应该很容易被面试官问:Object 的 wait 和 notify/notifyAll 如何实现线程同步?

在Object.java中,定义了wait(), notify()和notifyAll()等接口。wait()的作用是让当前线程进入等待状态,同时,wait() 也会让当前线程释放它所持有的锁。而 notify() 和 notifyAll() 的作用,则是唤醒当前对象上的等待线程;notify() 是唤醒单个线程,而 notifyAll() 是唤醒所有的线程。

wait 和 yield(或 sleep)的区别?

wait() 是让线程由“运行状态”进入到“等待(阻塞)状态”,而 yield() 是让线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;但是,并不能保证在当前线程调用 yield() 之后,其它具有相同优先级的线程就一定能获得执行权。
wait() 是会线程释放它所持有对象的同步锁,而 yield() 方法不会释放锁。
而我接触到的很多情况是:问线程同步的问题,大多数人基本上只知道 synchronized。

要搞清线程的同步问题,大家要先了解一下“对象的同步锁”,这个留给大家自己去看吧,这里不做展开。我们回到新接到的这个需求上来,这个场景其实挺合适做为一个面试题的。

如何实现呢?我想到一个简单的方法就是用CountDownLatch。

CountDownLatch:一个同步辅助类(大名鼎鼎的java.util.concurrent包),在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

用给定的任务数初始化 CountDownLatch,一个线程工作完成(任务成功或者失败都算工作完成)就调用 countDown() 方法,当计数到达零之前,await 方法会一直受阻塞。当计数器为零时,会释放所有等待的线程,await后的代码将被执行。

CountDownLatch 计数无法被重置。如果需要重置计数,请考虑使用 CyclicBarrier。

还有其他的实现方式吗?这个是肯定的。比如,真接上 Thread.jion,代码难看是会难看点,但也能完成这个需求。

我还查到一种方式是使用java.util.concurrent.ExecutorService的 awaitTermination 阻塞主线程,等待线程池的所有线程执行完成。需要设置一个超时时间的参数,如果超时则 awaitTermination 返回 false,如果线程池中的线程全部执行完成,返回 true。

你的朋友是不是也在准备面试呢?你可以把今天的题目分享给好友,或许你可以帮到他。

猜你喜欢

转载自blog.csdn.net/duoduo_11011/article/details/128252630