wait与notify

合集下载

多线程wait方法

多线程wait方法

多线程wait方法多线程wait方法是Java中的一个重要概念,它是用来实现线程之间的同步和协作的。

在Java中,每个对象都有一个锁,当一个线程获得了该对象的锁时,其他线程就无法访问该对象。

wait方法可以让一个线程释放该对象的锁,并进入等待状态,直到其他线程唤醒它。

wait方法的语法如下:```public final void wait() throws InterruptedException```该方法会使当前线程进入等待状态,直到其他线程调用该对象的notify或notifyAll方法唤醒它。

wait方法必须在synchronized块中调用,否则会抛出IllegalMonitorStateException异常。

wait方法还有一个重载方法,可以指定等待的时间:```public final void wait(long timeout) throws InterruptedException ```该方法会使当前线程进入等待状态,最多等待timeout毫秒,如果在等待期间没有其他线程唤醒它,就会自动唤醒。

wait方法的使用场景通常是在多线程之间进行协作。

例如,一个线程需要等待另一个线程完成某个操作后才能继续执行,就可以使用wait方法。

另外,wait方法也可以用来实现线程之间的通信,例如生产者-消费者模式中,消费者线程需要等待生产者线程生产数据后才能消费。

需要注意的是,wait方法会释放对象的锁,因此在调用wait方法前必须先获得该对象的锁。

另外,wait方法也可能会出现虚假唤醒的情况,即线程在没有被其他线程唤醒的情况下自行醒来,因此在使用wait方法时必须使用while循环来判断条件是否满足。

总之,多线程wait方法是Java中非常重要的一个概念,它可以实现线程之间的同步和协作,是多线程编程中必须掌握的知识点。

在使用wait方法时需要注意锁的获取和释放,以及虚假唤醒的情况,这样才能保证程序的正确性和稳定性。

信号量wait用法

信号量wait用法

信号量wait用法信号量是用来控制多线程并发执行的一种同步机制,常用的操作包括wait和signal。

wait是用来阻塞线程的操作,它可以设置一个初始值,当初始值小于等于0时,线程会被阻塞;当初始值大于0时,线程可以继续执行。

在使用wait时,通常会有两种情况:1.等待资源释放:当一个线程需要一个特定的资源,但该资源正在其他线程使用时,线程可以调用wait来等待资源释放。

例如,多个线程需要访问一个共享变量,但只能有一个线程访问该变量,其他线程需要等待,当该线程访问完之后调用signal来唤醒其他线程。

2.等待某个条件满足:当一个线程需要某个条件满足才能继续执行时,可以使用wait来等待条件的满足。

例如,一个线程需要等待某个标志位变为真时才能执行后续操作,可以调用wait来等待标志位变为真,当条件满足时,再调用signal来唤醒线程。

在使用wait时,需要注意以下几点:1. wait操作必须在synchronized块内进行,以确保在调用wait之前线程获得锁,否则会抛出IllegalMonitorStateE某ception异常。

2. wait操作会释放线程持有的锁,使得其他线程可以获得锁并执行。

3. 调用wait会使得线程进入等待状态,直到被其他线程唤醒。

可以使用signal或signalAll来唤醒线程,唤醒的线程将会重新竞争获取锁。

4. 在调用wait之前,通常需要判断某个条件是否满足,如果条件已经满足,则不需要等待,可以直接执行后续操作。

否则,调用wait进行等待。

5. wait可以设置超时时间,如果超过指定的时间仍未被唤醒,则会自动唤醒线程。

6. 如果有多个线程在等待同一个资源或条件的话,可以使用notifyAll来唤醒所有等待的线程,而不是只唤醒一个线程。

总结来说,信号量的wait操作是一种线程等待的机制,在需要等待某个资源释放或某个条件满足时使用。

它可以让线程进入等待状态,并释放持有的锁,以允许其他线程获得锁并执行。

sleep与wait有什么区别

sleep与wait有什么区别

sleep与wait有什么区别sleep()是使线程暂停执⾏⼀段时间的⽅法。

wait()也是⼀种使线程暂停执⾏的⽅法,例如,当线程交互时,如果线程对⼀个同步线程x发出⼀个wait()调⽤请求,那么该线程会暂停执⾏,被调对象进⼊等待状态,直到被唤醒或等待时间超时。

具体⽽⾔,sleep与wait的区别主要表现在以下⼏个⽅⾯:1)原理不同。

sleep是Thread类的静态⽅法,是线程⽤来控制⾃⾝流程的,它会使此线程暂停执⾏指定时间,⽽把执⾏机会会让给其他线程,等到计时时间到时,此线程会⾃动苏醒。

例如,当线程执⾏报时功能时,每⼀秒钟打印出⼀个时间,那么此时就需要在打印⽅法前⾯加上⼀个sleep⽅法,以便让⾃⼰每隔⼀秒执⾏⼀次,该过程如同闹钟⼀样。

⽽wait是Object类的⽅法,⽤于线程间的通信,这个⽅法会使当前拥有对象锁的进程等待,直到其他线程调⽤notify⽅法(或notifyAll⽅法)时才醒来。

⼀个开发⼈员也可以给它指定⼀个时间,⾃动醒来。

与wait配套的⽅法有notify和notifyAll。

2)对锁的处理机制不同。

由于sleep⽅法的主要作⽤是让线程休眠指定的⼀段时间,在时间到时⾃动恢复,不涉及线程间的通信,因此,调⽤sleep⽅法并不会释放锁。

⽽wait⽅法则不同,当调⽤wait⽅法后,线程会释放掉它所占⽤的锁,从⽽使线程所在对象的其他synchronized数据可被其他线程使⽤。

举个简单例⼦,在⼩明拿遥控器期间,他可以⽤⾃⼰的sleep⽅法每隔⼗分钟掉⼀次电视台,⽽在他调台休息的⼗分钟期间,遥控器还在他的⼿上。

3)使⽤区域不同。

由于wait⽅法的特殊意义,所以,它必须放在同步控制⽅法或者同步语句块使⽤,⽽sleep则可以放在任何地⽅使⽤。

4)sleep⽅法必须捕获异常,⽽wait,notify以及notifyall不需要捕捉异常。

在sleep的过程中,有可能被其他对象调⽤它的interrupt(),产⽣InterruptedException异常。

最全多线程经典面试题和答案

最全多线程经典面试题和答案

最全多线程经典⾯试题和答案Java实现线程有哪⼏种⽅式?1、继承Thread类实现多线程2、实现Runnable接⼝⽅式实现多线程3、使⽤ExecutorService、Callable、Future实现有返回结果的多线程多线程同步有哪⼏种⽅法?Synchronized关键字,Lock锁实现,分布式锁等。

Runnable和Thread⽤哪个好?Java不⽀持类的多重继承,但允许你实现多个接⼝。

所以如果你要继承其他类,也为了减少类之间的耦合性,Runnable会更好。

Java中notify和notifyAll有什么区别?notify()⽅法不能唤醒某个具体的线程,所以只有⼀个线程在等待的时候它才有⽤武之地。

⽽notifyAll()唤醒所有线程并允许他们争夺锁确保了⾄少有⼀个线程能继续运⾏。

为什么wait/notify/notifyAll这些⽅法不在thread类⾥⾯?这是个设计相关的问题,它考察的是⾯试者对现有系统和⼀些普遍存在但看起来不合理的事物的看法。

回答这些问题的时候,你要说明为什么把这些⽅法放在Object类⾥是有意义的,还有不把它放在Thread类⾥的原因。

⼀个很明显的原因是JAVA提供的锁是对象级的⽽不是线程级的,每个对象都有锁,通过线程获得。

如果线程需要等待某些锁那么调⽤对象中的wait()⽅法就有意义了。

如果wait()⽅法定义在Thread类中,线程正在等待的是哪个锁就不明显了。

简单的说,由于wait,notify和notifyAll都是锁级别的操作,所以把他们定义在Object类中因为锁属于对象。

为什么wait和notify⽅法要在同步块中调⽤?主要是因为Java API强制要求这样做,如果你不这么做,你的代码会抛出IllegalMonitorStateException异常。

还有⼀个原因是为了避免wait 和notify之间产⽣竞态条件。

什么是死锁?如何避免死锁?死锁就是两个线程相互等待对⽅释放对象锁。

java notify方法

java notify方法

java notify方法
Java中的notify()方法是线程间通信中的一个重要方法。

它是Object类中的方法,用于唤醒正在等待该对象锁的线程。

当一个线程调用了wait()方法后,它就会进入等待状态,直到其他线程调用了该对象的notify()方法,才会被唤醒。

notify()方法会随机地唤醒一个正在等待该对象锁的线程,如果有多个线程在等待,则只能随机唤醒一个线程,其他线程仍然处于等待状态。

使用notify()方法需要满足以下条件:
1. 该方法必须在synchronized块中调用,即必须先获得对象的锁才能调用该方法。

2. 该方法调用后,并不会立即释放对象锁,而是等到当前线程执行完synchronized块中的代码后,才会释放锁。

3. 如果有多个线程在等待该对象锁,notify()方法只能唤醒其中一个线程,其他线程仍然处于等待状态。

为了唤醒所有正在等待该对象锁的线程,可以使用notifyAll()方法。

该方法会唤醒所有正在等待该对象锁的线程,但同样需要在synchronized块中调用。

需要注意的是,在使用wait()和notify()方法时,必须在同一对象上调用。

如果在不同对象上调用,将会出现IllegalMonitorStateException异常。

总之,notify()方法是Java中线程间通信的重要方法之一,它能够实现多线程间的同步协作,避免因线程之间的竞争而导致的数据
不一致或死锁等问题。

熟练掌握notify()方法的使用,可以帮助我们更好地进行Java编程。

java多线程试题_答案

java多线程试题_答案

java多线程试题_答案多线程一.选择题1.下列说法中错误的一项是(A)A.线程就是程序B.线程是一个程序的单个执行流B.多线程是指一个程序的多个执行流D.多线程用于实现并发2.下列哪个一个操作不能使线程从等待阻塞状态进入对象阻塞状态(D)A.等待阴塞状态下的线程被notify()唤B.等待阻塞状态下的纯种被interrput()中断C.等待时间到D.等待阻塞状态下的线程调用wait()方法3.下列哪个方法可以使线程从运行状态进入其他阻塞状态(A)A.sleepB.waitC.yieldD.start4.下列说法中错误的一项是(D)A.一个线程是一个Thread类的实例B.线程从传递给纯种的Runnable实例run()方法开始执行C.线程操作的数据来自Runnable实例D.新建的线程调用start()方法就能立即进入运行状态5.下列关于Thread类提供的线程控制方法的说法中,错误的一项是(D)A.在线程A中执行线程B的join()方法,则线程A等待直到B执行完成B.线程A通过调用interrupt()方法来中断其阻塞状态C.若线程A调用方法isAlive()返回值为true,则说明A正在执行中D.currentThread()方法返回当前线程的引用6.下列说法中,错误的一项是()A.对象锁在synchronized()语句执行完之后由持有它的线程返还B.对象锁在synchronized()语句中出现异常时由持有它的线程返还C.当持有锁的线程调用了该对象的wait()方法时,线程将释放其持有的锁D.当持有锁的线程调用了该对象的构造方法时,线程将释放其持有的锁7.下面的哪一个关键字通常用来对对象的加锁,从而使得对对象的访问是排他的 AA.sirialize B transient C synchronized D static二.填空题1. 在操作系统中,被称做轻型的进程是线程2. 多线程程序设计的含义是可以将一个程序任务分成几个并行的任务3. 在Java程序中,run()方法的实现有两种方式:实现Runnable 接口和继承Thread类4 .多个线程并发执行时,各个线程中语句的执行顺序是确定的,但是线程之间的相对执行顺序是不确定的6.Java中的对象锁是一种独占的排他锁7.程序中可能出现一种情况:多个线种互相等待对方持有的锁,而在得到对方的锁之前都不会释放自己的锁,这就是死锁8.线程的优先级是在Thread类的常数MIN_PRIORITY 和MAX_PRIORITY之间的一个值9.处于新建状态的线程可以使用的控制方法是start() 和stop() 。

notifyall方法

notifyall方法
notifyAll方法是Java中Object类中的一个方法,用于唤醒正在等待同一对象锁的所有线程。

当一个线程调用wait方法时,它会进入等待状态并释放对象的锁。

想要重新获得对象的锁,就必须等待其他线程
释放同一对象的锁,并通过notify或notifyAll方法来唤醒。

notifyAll方法的调用方式与notify方法相似,只不过notify方法只会唤醒一个等待线程,而notifyAll方法会唤醒所有等待线程。

因此,在多线程编程中,使用notifyAll方法可以确保所有等待线程都有机会获得锁并执行任务。

在实际应用中,notifyAll方法通常用于多个线程共同协作完成同一个
任务的场景下。

例如,在生产者-消费者模式中,当生产者生产完数据后,需要通知消费者来消费数据。

这时可以使用notifyAll方法来唤醒所有等待的消费者线程,确保消费者线程都有机会取得锁并消费数据。

另外需要注意的是,notifyAll方法不会立即释放锁。

它会等到当前线
程完成任务并执行完notifyAll方法后,才会将对象的锁释放,让其他等待线程有机会获得锁并执行。

因此,在使用notifyAll方法时,应该谨慎考虑是否需要释放对象锁,以避免出现死锁等问题。

综上所述,notifyAll方法是Java中多线程编程中非常重要的一个方法,它能够唤醒所有正在等待同一对象锁的线程,并确保它们都有机会获
得锁并执行任务。

在实际应用中,应该注意使用时的注意事项,以避
免出现死锁等问题。

wait方法使用场景

wait方法使用场景介绍如下:
在编程中,wait() 方法通常用于线程间的同步。

当一个线程需要等待另一个线程完成某些任务后再继续执行时,可以使用wait() 方法来实现等待。

wait() 方法通常用于多线程编程中的互斥锁(mutex)机制。

当一个线程获得了某个互斥锁后,如果需要等待另一个线程释放该锁,就可以使用wait() 方法。

在调用wait() 方法后,当前线程会被阻塞,直到其他线程调用notify() 或notify_all() 方法来唤醒它。

具体来说,wait() 方法一般包含以下步骤:
1.获取互斥锁
std::unique_lock<std::mutex> lock(m_mutex);
2.判断条件是否满足,如果不满足,则等待
m_cv.wait(lock, [this]() { return m_condition; });
这里m_cv 是一个条件变量,m_condition 是一个标志,表示某个条件是否满足。

如果条件不满足,就会调用wait() 方法来等待。

wait() 方法会将当前线程阻塞,并释放互斥锁,直到其他线程调用notify() 或notify_all() 方法来唤醒它。

3.条件满足后执行相应操作
// do something
在其他线程满足条件后调用notify() 或notify_all() 方法来唤醒等待的线程,被唤醒的线程会重新尝试获取互斥锁,并判断条件是否满足。

如果条件满足,则会继续执行相应操作。

java线程学习之notify方法和notifyAll方法

java线程学习之notify⽅法和notifyAll⽅法notify(通知)⽅法,会将等待队列中的⼀个线程取出。

⽐如obj.notify();那么obj的等待队列中就会有⼀个线程选中并且唤醒,然后被唤醒的队列就会退出等待队列。

活跃线程调⽤等待队列中的线程时,因为现在的活跃线程还⽤有锁,会先将synchronized代码块执⾏完毕,释放对象监视器,被唤醒的线程才会获得这个监视器,然后被唤醒的线程才能继续执⾏。

也就是说原来在等待队列中的线程被唤醒后,在被执⾏notify的⼀瞬间并不会⽴刻执⾏,因为在被执⾏notify的⼀瞬间,原来执⾏notify的线程还持有着锁,所以其他线程还⽆法获取这个实例的锁。

举个例⼦:假设熊⼤和熊⼆都要到⼩⿊屋⾥⾯壁⼗分钟,⼩⿊屋同⼀时刻只能允许⼀只熊进⾏⾯壁思过。

熊⼤先进开始⾯壁思过同时把门锁上(相当于执⾏synchronized代码块拥有锁),结果在熊⼤⾯壁到三分钟的时候,困了想去睡觉(相当于执⾏wait()⽅法,进去到等待队列),这时它⾛出了门(相当于释放锁)去睡觉,熊⼆开始进来进⾏⾯壁思过,当熊⼆⾯壁到6分钟的时候,喊了⼀声让熊⼤接着来⾯壁思过(相当于执⾏notify⽅法),因为熊⼆还在继续⾯壁思过,所以熊⼤要在⼩⿊屋外⼀直等,等到熊⼆⾯壁结束后(释放了锁),才能进去接着⾯壁,⾯壁剩余的七分钟,所以说即使熊⼆在第6分钟叫醒了熊⼤,但因为此时熊⼆在⼩⿊屋⾥,熊⼤也不可能第⼀时间⾯壁思过。

如果说等待队列中的线程不⽌⼀个,那么当执⾏notify的时候叫醒那⼀个呢,被唤醒的线程是随机选择的。

那么被唤醒的线程在作为锁定此对象的下⼀个线程⽅⾯没有可靠的特权或劣势。

notifyAll(通知全部)⽅法是将等待队列中的所以线程都唤醒,⽤法和notify⼀样。

区别是notify只能唤醒等待队列中的⼀个,⽽notifyAll却能唤醒等待队列中的全部。

在实际使⽤时,是使⽤notify还是notifyAll,那个更好呢。

object.wait原理

object.wait原理
简单地说wait()方法是让当前线程处于阻塞状态,并且等待其他线程调用notify()或notifyAll()方法来唤醒该线程,当然这个要在同步环境之下,也就是说wait()方法必须在同步方法或同步控制块里调用。

它的使用也比较简单,当一个线程执行到wait()方法时候就会释放它所持有的对象锁,从而允许其他线程可以访问并且操作这个对象,而当其他线程调用notify()或notifyAll() 方法来唤醒该线程的时候,线程就会去获取对象锁,从而重新回到运行状态。

如果在没有同步的情况下调用wait()方法就会导致IllegalMonitorStateException 异常,wait()方法的作用就是让线程暂时停止执行并且释放它所独占的资源,也便于其他线程有机会使用该资源。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

java,wait与notify
Java 2009-10-13 19:25:44 阅读662 评论0 字号:大中小 订阅
wait与notify是java同步机制中重要的组成部分。结合与synchronized关键字使用,可以建立很多
优秀的同步模型。

synchronized(this){}等价与public synchronized void method(){.....}
同步分为类级别和对象级别,分别对应着类锁和对象锁。类锁是每个类只有一个,如果static的
方法被synchronized关键字修饰,则在这个方法被执行前必须获得类锁;对象锁类同。

首先,调用一个Object的wait与notify/notifyAll的时候,必须保证调用代码对该Object是同步
的,也就是说必须在作用等同于synchronized(obj){......}的内部才能够去调用obj的wait与notify/notifyAll
三个方法,否则就会报错:

java.lang.IllegalMonitorStateException: current thread not owner
在调用wait的时候,线程自动释放其占有的对象锁,同时不会去申请对象锁。当线程被唤醒的
时候,它才再次获得了去获得对象锁的权利。

所以,notify与notifyAll没有太多的区别,只是notify仅唤醒一个线程并允许它去获得锁,notifyAll
是唤醒所有等待这个对象的线程并允许它们去获得对象锁,只要是在synchronied块中的代码,没有对象
锁是寸步难行的。其实唤醒一个线程就是重新允许这个线程去获得对象锁并向下运行。

顺便说一下notifyall,虽然是对每个wait的对象都调用一次notify,但是这个还是有顺序的,每
个对象都保存这一个等待对象链,调用的顺序就是这个链的顺序。其实启动等待对象链中各个线程的也是
一个线程,在具体应用的时候,需要注意一下。

class ThreadA
{
public static void main(String[] args)
{
ThreadB b=new ThreadB();
b.start();
System.out.println("b is start....");
synchronized(b)//括号里的b是什么意思,起什么作用?
{
try
{
System.out.println("Waiting for b to complete...");
b.wait();//这一句是什么意思,究竟让谁wait?
System.out.println("Completed.Now back to main thread");
}catch (InterruptedException e){}
}
System.out.println("Total is :"+b.total);
}
}
class ThreadB extends Thread
{
int total;
public void run()
{
synchronized(this)
{
System.out.println("ThreadB is running..");
for (int i=0;i<100;i++ )
{
total +=i;
System.out.println("total is "+total);
}
notify();
}
}
}
要分析这个程序,首先要理解notify()和wait(),为什么在前几天纪录线程的时候没有纪录这两个方法
呢,因为这两个方法本来就不属于Thread类,而是属于最底层的object基础类的,也就是说不光是Thread,
每个对象都有notify和wait的功能,为什么?因为他们是用来操纵锁的,而每个对象都有锁,锁是每个对象
的基础,既然锁是基础的,那么操纵锁的方法当然也是最基础了.

再往下看之前呢,首先最好复习一下Think in Java的14.3.1中第3部分内容:等待和通知,也就是
wait()和notify了.

按照Think in Java中的解释:"wait()允许我们将线程置入“睡眠”状态,同时又“积极”地等待条件发生改
变.而且只有在一个notify()或notifyAll()发生变化的时候,线程才会被唤醒,并检查条件是否有变."
我们来解释一下这句话.
"wait()允许我们将线程置入“睡眠”状态",也就是说,wait也是让当前线程阻塞的,这一点和sleep或
者suspend是相同的.那和sleep,suspend有什么区别呢?

区别在于"(wait)同时又“积极”地等待条件发生改变",这一点很关键,sleep和suspend无法做到.因
为我们有时候需要通过同步(synchronized)的帮助来防止线程之间的冲突,而一旦使用同步,就要锁定对
象,也就是获取对象锁,其它要使用该对象锁的线程都只能排队等着,等到同步方法或者同步块里的程序全部
运行完才有机会.在同步方法和同步块中,无论sleep()还是suspend()都不可能自己被调用的时候解除锁定,
他们都霸占着正在使用的对象锁不放.

而wait却可以,它可以让同步方法或者同步块暂时放弃对象锁,而将它暂时让给其它需要对象锁的
人(这里应该是程序块,或线程)用,这意味着可在执行wait()期间调用线程对象中的其他同步方法!在其它情况
下(sleep啊,suspend啊),这是不可能的.

但是注意我前面说的,只是暂时放弃对象锁,暂时给其它线程使用,我wait所在的线程还是要把这个
对象锁收回来的呀.wait什么?就是wait别人用完了还给我啊!

好,那怎么把对象锁收回来呢?
第一种方法,限定借出去的时间.在wait()中设置参数,比如wait(1000),以毫秒为单位,就表明我只借
出去1秒中,一秒钟之后,我自动收回.

第二种方法,让借出去的人通知我,他用完了,要还给我了.这时,我马上就收回来.哎,假如我设了1小
时之后收回,别人只用了半小时就完了,那怎么办呢?靠!当然用完了就收回了,还管我设的是多长时间啊.

那么别人怎么通知我呢?相信大家都可以想到了,notify(),这就是最后一句话"而且只有在一个
notify()或notifyAll()发生变化的时候,线程才会被唤醒"的意思了.

因此,我们可将一个wait()和notify()置入任何同步方法或同步块内部,无论在那个类里是否准备进
行涉及线程的处理。而且实际上,我们也只能在同步方法或者同步块里面调用wait()和notify().

这个时候我们来解释上面的程序,简直是易如反掌了.
synchronized(b){...};的意思是定义一个同步块,使用b作为资源锁。b.wait();的意思是临时释放
锁,并阻塞当前线程,好让其他使用同一把锁的线程有机会执行,在这里要用同一把锁的就是b线程本身.这
个线程在执行到一定地方后用notify()通知wait的线程,锁已经用完,待notify()所在的同步块运行完之后,wait
所在的线程就可以继续执行.

相关文档
最新文档