首页 > 试题广场 >

以下哪几种方式可用来实现线程间通知和唤醒?

[不定项选择题]
以下哪几种方式可用来实现线程间通知和唤醒:( )
  • Object.wait/notify/notifyAll
  • ReentrantLock.wait/notify/notifyAll
  • Condition.await/signal/signalAll
  • Thread.wait/notify/notifyAll
wait()、notify()和notifyAll()是 Object类 中的方法

从这三个方法的文字描述可以知道以下几点信息:

1)wait()、notify()和notifyAll()方法是本地方法,并且为final方法,无法被重写。


2)调用某个对象的wait()方法能让当前线程阻塞,并且当前线程必须拥有此对象的monitor(即锁)

3)调用某个对象的notify()方法能够唤醒一个正在等待这个对象的monitor的线程,如果有多个线程都在等待这个对象的monitor,则只能唤醒其中一个线程;

4)调用notifyAll()方法能够唤醒所有正在等待这个对象的monitor的线程;

有朋友可能会有疑问:为何这三个不是Thread类声明中的方法,而是Object类中声明的方法

(当然由于Thread类继承了Object类,所以Thread也可以调用者三个方法)?其实这个问

题很简单,由于每个对象都拥有monitor(即锁),所以让当前线程等待某个对象的锁,当然

应该通过这个对象来操作了。而不是用当前线程来操作,因为当前线程可能会等待多个线程

的锁,如果通过线程来操作,就非常复杂了。

上面已经提到,如果调用某个对象的wait()方法,当前线程必须拥有这个对象的monitor(即

锁),因此调用wait()方法必须在同步块或者同步方法中进行(synchronized块或者

synchronized方法)。

调用某个对象的wait()方法,相当于让当前线程交出此对象的monitor,然后进入等待状态,

等待后续再次获得此对象的锁(Thread类中的sleep方法使当前线程暂停执行一段时间,从

而让其他线程有机会继续执行,但它并不释放对象锁);

notify()方法能够唤醒一个正在等待该对象的monitor的线程,当有多个线程都在等待该对象

的monitor的话,则只能唤醒其中一个线程,具体唤醒哪个线程则不得而知。

同样地,调用某个对象的notify()方法,当前线程也必须拥有这个对象的monitor,因此调用

notify()方法必须在同步块或者同步方法中进行(synchronized块或者synchronized方法)。

nofityAll()方法能够唤醒所有正在等待该对象的monitor的线程,这一点与notify()方法是不同的。
Condition是在java 1.5中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作,相比使用Object的wait()、notify(),使用Condition1的await()、signal()这种方式实现线程间协作更加安全和高效。因此通常来说比较推荐使用Condition,在阻塞队列那一篇博文中就讲述到了,阻塞队列实际上是使用了Condition来模拟线程间协作。
  • Condition是个接口,基本的方法就是await()和signal()方法;
  • Condition依赖于Lock接口,生成一个Condition的基本代码是lock.newCondition()
  • 调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用Conditon中的await()对应Object的wait(); Condition中的signal()对应Object的notify(); Condition中的signalAll()对应Object的notifyAll()
编辑于 2016-08-29 16:55:46 回复(33)
wait()、notify()和notifyAll()是 Object类 中的方法 从这三个方法的文字描述可以知道以下几点信息: 1)wait()、notify()和notifyAll()方法是本地方法,并且为final方法,无法被重写。 2)调用某个对象的wait()方法能让当前线程阻塞,并且当前线程必须拥有此对象的monitor(即锁) 3)调用某个对象的notify()方法能够唤醒一个正在等待这个对象的monitor的线程,如果有多个线程都在等待这个对象的monitor,则只能唤醒其中一个线程; 4)调用notifyAll()方法能够唤醒所有正在等待这个对象的monitor的线程; 有朋友可能会有疑问:为何这三个不是Thread类声明中的方法,而是Object类中声明的方法 (当然由于Thread类继承了Object类,所以Thread也可以调用者三个方法)?其实这个问 题很简单,由于每个对象都拥有monitor(即锁),所以让当前线程等待某个对象的锁,当然 应该通过这个对象来操作了。而不是用当前线程来操作,因为当前线程可能会等待多个线程 的锁,如果通过线程来操作,就非常复杂了。 上面已经提到,如果调用某个对象的wait()方法,当前线程必须拥有这个对象的monitor(即 锁),因此调用wait()方法必须在同步块或者同步方法中进行(synchronized块或者 synchronized方法)。 调用某个对象的wait()方法,相当于让当前线程交出此对象的monitor,然后进入等待状态, 等待后续再次获得此对象的锁(Thread类中的sleep方法使当前线程暂停执行一段时间,从 而让其他线程有机会继续执行,但它并不释放对象锁); notify()方法能够唤醒一个正在等待该对象的monitor的线程,当有多个线程都在等待该对象 的monitor的话,则只能唤醒其中一个线程,具体唤醒哪个线程则不得而知。 同样地,调用某个对象的notify()方法,当前线程也必须拥有这个对象的monitor,因此调用 notify()方法必须在同步块或者同步方法中进行(synchronized块或者synchronized方法)。 nofityAll()方法能够唤醒所有正在等待该对象的monitor的线程,这一点与notify()方法是不同的。 Condition是在java 1.5中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作,相比使用Object的wait()、notify(),使用Condition1的await()、signal()这种方式实现线程间协作更加安全和高效。因此通常来说比较推荐使用Condition,在阻塞队列那一篇博文中就讲述到了,阻塞队列实际上是使用了Condition来模拟线程间协作。 Condition是个接口,基本的方法就是await()和signal()方法; Condition依赖于Lock接口,生成一个Condition的基本代码是lock.newCondition() 调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用Conditon中的await()对应Object的wait(); Condition中的signal()对应Object的notify(); Condition中的signalAll()对应Object的notifyAll()
编辑于 2020-10-03 21:56:22 回复(0)
这道题好难啊
发表于 2018-08-10 09:53:44 回复(0)
木有解释下B选项的吗
发表于 2018-07-14 20:01:18 回复(0)
reentrantlock要实现线程间的通信,必须创建条件锁
发表于 2018-03-02 16:25:26 回复(0)
题目问的意思应该是方法的本属类,不包括继承,我是这么理解的。
发表于 2017-10-19 08:40:00 回复(0)
sig是传递给它的唯一参数。执行了signal()调用后,进程只要接收到类型为sig的信号,不管其正在执行程序的哪一部分,就立即执行func()函数。当func()函数执行结束后,控制权返回进程被中断的那一点继续执行。
发表于 2016-01-31 16:46:38 回复(1)
wait()、notify()和notifyAll()是 Object类 中的方法
Condition是在java 1.5中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作,相比使用Object的wait()、 notify(),使用Condition1的await()、signal()这种方式实现线程间协作更加安全和高效。
发表于 2016-04-22 21:47:46 回复(0)
C错: ReentrantLock使用lock和unlock
D错: Thread的wait/notify/notifyAll继承自Object.没有自己实现.
发表于 2019-03-26 14:29:43 回复(4)

什么都是object,所以我愉快的选了ABCD

发表于 2018-08-09 10:40:50 回复(10)
A. wait/notify/notifyAll是Object类的方法,而不是Thread类的。Thread类对线程执行控制的的方法是sleep。
编辑于 2015-10-20 21:01:00 回复(3)
72%头像 72%
为什么thread.wait()和notify()不可以,我看到一个解释是这样的:
wait()和notify()方法是object类中的方法,thread类继承object类,但是对于线程来讲,单个线程可能同时获得了多个对象的锁,如果调用thread.wait()会使线程释放所有锁,如果调用某个对象的wait()就可以只释放此对象的锁。
发表于 2019-12-24 13:22:57 回复(0)
所有的对象都有wait和notify,所以我认为全部正确
发表于 2017-01-20 11:36:08 回复(0)
准确的说 线程间同步和互斥是调用Lock对象的Condition对象的。它提供了三个方法: wait/signal/signalAll方法。

await方法可以让当前线程处于等待状态,直到某条件发生
signal方法用于唤醒一个等待的线程,signalAll方法用于唤醒所有等待的线程

A可以但是这个是通过对象的内置监视器来实现线程通信的,不能说不对,但C肯定是正确的!
发表于 2015-09-07 20:00:34 回复(0)
为什么D是错误的,Thread也是继承自Object,那么Object有的方法其实它也有,它自己给自己加锁难道不行吗?只需要有人给他唤醒就可以吧?
发表于 2016-08-31 11:49:12 回复(1)
AC不用说,BD用Object的原生方法有什么问题呢?子类都没法重写。虽然它们是锁和线程对象,但是我可以用他们的wait、notify机制阿,有什么问题?
发表于 2022-05-13 13:44:33 回复(0)
ReentrantLock是lock和unlock方法。

发表于 2022-01-31 12:39:35 回复(0)
完美的避开了所有正确的选项
编辑于 2019-10-12 17:32:08 回复(0)
Condition是在java 1.5中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作,相比使用Object的wait()、notify(),使用Condition1的await()、signal()这种方式实现线程间协作更加安全和高效。因此通常来说比较推荐使用Condition,在阻塞队列那一篇博文中就讲述到了,阻塞队列实际上是使用了Condition来模拟线程间协作。
发表于 2017-08-08 00:36:23 回复(0)
成功避开所有答案
发表于 2022-04-30 21:18:09 回复(0)