导航:首页 > 编程语言 > java线程notify

java线程notify

发布时间:2022-06-13 10:58:08

A. 如何在 java 中正确使用 wait,notify 和 notifyAll

wait, notify 和 notifyAll,这些在多线程中被经常用到的保留关键字,在实际开发的时候很多时候却并没有被大家重视。本文对这些关键字的使用进行了描述。

在 Java 中可以用 wait、notify 和 notifyAll 来实现线程间的通信。。举个例子,如果你的Java程序中有两个线程——即生产者和消费者,那么生产者可以通知消费者,让消费者开始消耗数据,因为队列缓冲区中有内容待消费(不为空)。相应的,消费者可以通知生产者可以开始生成更多的数据,因为当它消耗掉某些数据后缓冲区不再为满。

我们可以利用wait()来让一个线程在某些条件下暂停运行。例如,在生产者消费者模型中,生产者线程在缓冲区为满的时候,消费者在缓冲区为空的时候,都应该暂停运行。如果某些线程在等待某些条件触发,那当那些条件为真时,你可以用 notify 和 notifyAll 来通知那些等待中的线程重新开始运行。不同之处在于,notify 仅仅通知一个线程,并且我们不知道哪个线程会收到通知,然而 notifyAll 会通知所有等待中的线程。换言之,如果只有一个线程在等待一个信号灯,notify和notifyAll都会通知到这个线程。但如果多个线程在等待这个信号灯,那么notify只会通知到其中一个,而其它线程并不会收到任何通知,而notifyAll会唤醒所有等待中的线程。

在这篇文章中你将会学到如何使用 wait、notify 和 notifyAll 来实现线程间的通信,从而解决生产者消费者问题。如果你想要更深入地学习Java中的多线程同步问题,我强烈推荐阅读Brian Goetz所着的《Java Concurrency in Practice | Java 并发实践》,不读这本书你的 Java 多线程征程就不完整哦!这是我最向Java开发者推荐的书之一。

如何使用Wait

尽管关于wait和notify的概念很基础,它们也都是Object类的函数,但用它们来写代码却并不简单。如果你在面试中让应聘者来手写代码,用wait和notify解决生产者消费者问题,我几乎可以肯定他们中的大多数都会无所适从或者犯下

B. java线程中notify什么意思

每个对象都有一个监视器,wait和notify都必须针对同一个监视器,
Student中notify是通知在this上等待的线程,wait是让出this的监视器,等待其它线程在this上的通知
Teacher中wait是等待其它线程在this上的通知,而且也没有通知其它线程,与Student不对应
大致代码如下:
Student:
synchronized(Test.class)
{
while(true)
{
//do....
Test.class.notify();
Test.class.wait();
}
}
Teacher:
synchronized(Test.class)
{
Test.class.wiat();
//do....
Test.class.nofity();
}

C. java 线程中wait和notify的问题

这个程序挺经典的.

我不知道你对wait这是不是很熟,我按我的说,有问题再沟通:

首先看
main函数,两句话,Procer对象和Consumer对象都引用了同一个p.
Procer类的run
前面有
synchronized(p)
说明该线程用到 synchronized 里的对象变量时,别的线程只能等待.
再看
if(p.bFull) {
try{p.wait();} catch (Exception e) {}
}
也就是说该线程用到了p对象,
而如果当运行到该线程时,
且p.bFull为真时
该线程进行等待,让其他线程运行

到这的思路如果没有问题,
那么我们假设
假设
p.bFull为假,
那么会再往下运行
也就是设置姓名,性别,
此时p.bFull仍然为假

之后设置 p.bFull 为真
p.notify()
当设置p.bFull为真时,表示下次如果仍然是该线程执行,将会wait.
而p.notify()是为了解以p为锁的线程,因为当前线程正在运行,所以当前线程肯定不需要解锁,那可能需要被解锁的,也就是Consumer对象的线程.

当前线程从开始运行到目前的位置,Consumer线程是一直在wait的,因为Consumer线程在while下面直接就synchronized (p)也就是这两个线程同时只能一个线程运行.
也就是说,要么这次运行Procer,要么运行Consumer
按我上面说的,Procer的运行逻辑应该已经清楚了,而Consumer的线程运行逻辑跟Procer一样,我就不多说了,

问题的关键在于
当Procer运行一次,之后Consumer运行一次,是比较好理解,交叉运行呗.
但如果Procer运行完,又运行了Procer线程,而没有让Consumer运行的时候,程序会怎么运行?(反之一样)
我下面来解释.
当Procer运行一次,又运行了Procer时,这时因为没有Consumer线程的介入
,p的bFull应该为真,
这时运行到
Procer线程的
if (p.bFull) {
try {
p.wait();
} catch (Exception e) {
}
时,因为p.bFull为真了,
所以运行下面的代码,
也就是让当前线程等待,而用来等待的锁就是p
这时,当前线程等待了,
也就要执行Consumer线程了,也就是相当于强制切换线程
运行一次Consumer线程后,Procer仍然在等待,如果这样,那就会仍然运行Consumer线程,根据逻辑,Consumer会像Procer一样,由于
if(!p.bFull) {
try{p.wait(); } catch (Exception e) {} }
而等待
这样两个线程都等待了
(如果你问,当!p.bFull如果成立,那p.bFull就不成立,那Procer不是该运行了吗?但是,我刚刚的假设是当Procer已经等待时,那么Procer就不会因为p.bFull的改变而继续运行了)

按上面所说,如果按这样的逻辑,最终会导致两个线程同时等待没有解锁,
为了解决这个问题,
就在程序的每个线程的
p.bFull = false;
后面,加上了
p.notify();
让以p为锁的线程解锁等待.
这样,就可以使程序的两个线程来回切换了.

D. JAVA多线程suspend,resume和wait,notify的区别

suspend,使线程进入停滞状态,除非收到resume消息,否则该线程不会变回可执行状态。
wait():使一个线程处于等待状态,并且释放所持有的对象的lock;
sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方
法要捕捉InterruptedException异常;
notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,
并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且
不是按优先级;
notityAll():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一
个对象的锁,而是让它们竞争。

E. 关于java的多线程问题,notify方法调用之后这个方法会发生什么下面的赋值会被执行吗

会执行,notify使得wait在this对象上的线程投入运行。
不过这个写法会有问题,notify调用后,不能确定当前线程和其他线程运行的顺序
如果其他线程要访问isRunning这个变量,会造成bug。

F. 帮忙解释一下java中类的notify的含义,多谢了

1、notify()方法的含义:

(1)notify()方法是随机唤醒一个线程,将等待队列中的一个等待线程从等待队列中移到同步队列中。

(2)在执行完notify()方法后,当前线程不会马上释放该对象锁,呈wait状态的线程也不能马上获得该对象锁。

要等到执行notify方法的线程将程序执行完 ,也就是退出sychronized代码块后,当前线程才会释放锁。而在同步队列中的该线程才可以获取该对象锁。

2、对象所释放的三个场景:

(1)执行完同步代码块就会释放对象锁;

(2)在执行代码块的过程中,遇到异常而导致线程终止,也会释放对象锁;

(3)在执行同步代码块的过程中,执行了锁所属对象的wait()方法,这个线程会释放对象锁,而此线程对象会进入线程等待池中,等待被唤醒。

(6)java线程notify扩展阅读

Java中notify和notifyAll的区别:

Java提供了两个方法notify和notifyAll来唤醒在某些条件下等待的线程,你可以使用它们中的任何一个,但是Java中的notify和notifyAll之间存在细微差别,这使得它成为Java中流行的多线程面试问题之一。

当你调用notify时,只有一个等待线程会被唤醒而且它不能保证哪个线程会被唤醒,这取决于线程调度器。

虽然如果你调用notifyAll方法,那么等待该锁的所有线程都会被唤醒,但是在执行剩余的代码之前,所有被唤醒的线程都将争夺锁定,这就是为什么在循环上调用wait。

因为如果多个线程被唤醒,那么线程是将获得锁定将首先执行,它可能会重置等待条件,这将迫使后续线程等待。

因此,notify和notifyAll之间的关键区别在于notify()只会唤醒一个线程,而notifyAll方法将唤醒所有线程。



G. 关于JAVA中线程notify()方法的一些问题

在多线路程中经常用到。
当在一个线程A中执行
wait()后,这个线程就会处于等待状态。
如果想重新激活线程A,继续向下执行代码,就必须在另一个线程中来激活线程A
class
A
extends
Thread
{
public
void
run()
{
wait();
System.out.println("end");
}
public
synrhonized
void
abc()
{
notify();
}
}
class
B
extends
Therad
{
public
void
run()
{
synchronized(A){A.notify()};
//激活

A.abc();
//激活
}
}
上面的代码只是一个形式。

H. java notify是不是唤醒本线程外的其他所有线程啊

线程安全 调用synchronized()
1.同一时刻 只有一个线程进入代码块 离开后让出cpu别的线程才进入
2.在任一方法中加synchronizeed() 那么此方法一次只能调用一次

synchronized代码被执行期间,线程可以调用对象的wait()方法,释放对象锁标志,进入等待状态,并且可以调用notify()或者 notifyAll()方法通知正在等待的其他线程。notify()通知等待队列中的第一个线程,notifyAll()通知的是等待队列中的所有线程

I. java中的notify和notifyAll有什么区别

首先从名字可以了解,notify是通知一个线程获取锁,notifyAll是通知所有相关的线程去竞争锁。

notify不能保证获得锁的线程,真正需要锁,并且可能产生死锁。

举例1:

所有人(消费者线程)准备吃饭,食堂没有开放(没有释放锁)打饭窗口(锁),所有人等待(WAITING)。

食堂开饭打饭窗口(释放锁),并广播消息“开饭了”(notifyAll),所有人竞争排队,并等待吃饭(BLOCKED)。每一个人依次在打饭窗口(获得锁)打饭(RUNNABLE)。如果想吃饭就打完饭后离开(释放锁),不想吃饭就直接离开(释放锁)。如果吃完了还想吃,就主动等待下一次“开饭了”的消息(wait)。

食堂通知一个人来吃饭(notify),此人来到打饭窗口(获得锁)打饭(RUNNABLE),其他人都在等待开饭的消息(WAITING)。如果想吃饭就打完饭后离开(释放锁),不想吃饭就直接离开(释放锁)。如果吃完了还想吃,就主动等待下一次“开饭”的消息(WAITING)。
notify不能保证通知到真正想吃饭的人。

举例2:

两个生产者P1、P2,两个消费者C1、C2,共同操作一个队列,队列最大长度为1。

开始P1、P2、C1、C2都处于运行状态(RUNNABLE)。

C1先获得锁,P1、P2、C2为BLOCKED状态。C1发现队列为空,主动进入WAITING。C2接着获得锁,成为RUNNABLE状态,发现队列为空,主动进入WAITING。

P1接着获得锁,成为RUNNABLE状态,在队列中插入一个元素,notify到了另一个生产者P2。P1循环生产,发现队列不为空,成为WAITING。

P2成为RUNNABLE状态,发现队列有值,主动进入WAITING。

此时锁已被释放,但P1、P2、C1、C2都处于WAITING状态,没有线程去获取锁,死了。




notify()和notifyAll()都是Object对象用于通知处在等待该对象的线程的方法。两者的最大区别在于:

notifyAll使所有原来在该对象上等待被notify的线程统统退出wait的状态,变成等待该对象上的锁,一旦该对象被解锁,他们就会去竞争。
notify则文明得多他只是选择一个wait状态线程进行通知,并使它获得该对象上的锁,但不惊动其他同样在等待被该对象notify的线程们,当第一个线程运行完毕以后释放对象上的锁此时如果该对象没有再次使用notify语句,则即便该对象已经空闲,其他wait状态等待的线程由于没有得到该对象的通知,继续处在wait状态,直到这个对象发出一个notify或notifyAll,它们等待的是被notify或notifyAll,而不是锁。

下面是一个很好的例子:


importjava.util.*;
classWidget...{}
classWidgetMakerextendsThread...{
List<Widget>finishedWidgets=newArrayList<Widget>();
publicvoidrun()...{
try...{
while(true)...{
Thread.sleep(5000);//actbusy
Widgetw=newWidget();
//也就是说需要5秒钟才能新产生一个Widget,这决定了一定要用notify而不是notifyAll
//因为上面两行代码不是同步的,如果用notifyAll则所有线程都企图冲出wait状态
//第一个线程得到了锁,并取走了Widget(这个过程的时间小于5秒,新的Widget还没有生成)
//并且解开了锁,然后第二个线程获得锁(因为用了notifyAll其他线程不再等待notify语句
//,而是等待finishedWidgets上的锁,一旦锁放开了,他们就会竞争运行),运行
//finishedWidgets.remove(0),但是由于finishedWidgets现在还是空的,
//于是产生异常
//***********这就是为什么下面的那一句不能用notifyAll而是要用notify

synchronized(finishedWidgets)...{
finishedWidgets.add(w);
finishedWidgets.notify();//这里只能是notify而不能是notifyAll
}
}
}
catch(InterruptedExceptione)...{}
}

publicWidgetwaitForWidget()...{
synchronized(finishedWidgets)...{
if(finishedWidgets.size()==0)...{
try...{
finishedWidgets.wait();
}
catch(InterruptedExceptione)
...{}
}
returnfinishedWidgets.remove(0);
}
}
}
...{
privateWidgetMakermaker;
publicWidgetUser(Stringname,WidgetMakermaker)...{
super(name);
this.maker=maker;
}
publicvoidrun()...{
Widgetw=maker.waitForWidget();
System.out.println(getName()+"gotawidget");
}

publicstaticvoidmain(String[]args)...{
WidgetMakermaker=newWidgetMaker();
maker.start();
newWidgetUser("Lenny",maker).start();
newWidgetUser("Moe",maker).start();
newWidgetUser("Curly",maker).start();
}
}

J. java中notify怎么使用

notify(),notifyAll()都是要唤醒正在等待的线程,前者明确唤醒一个,后者唤醒全部。
当程序不明确知道下一个要唤醒的线程时,需要采用notifyAll()唤醒所有在wait池中的线程,让它们竞争而获取资源的执行权,但使用notifyAll()时,会出现死锁的风险,因此,如果程序中明确知道下一个要唤醒的线程时,尽可能使用notify()而非notifyAll()。

阅读全文

与java线程notify相关的资料

热点内容
oa服务器异常怎么办 浏览:68
cmd编译utf8 浏览:276
怎么截取app接受的数据 浏览:276
nrf24l01pdf 浏览:298
php字符串转array 浏览:434
U盘分了文件夹后 浏览:940
javasetstring 浏览:837
压缩包里文件夹是白色的 浏览:472
编译链接知乎 浏览:591
php查询按钮 浏览:715
有音响游戏解压神器 浏览:253
怎么压缩图片jpeg 浏览:713
澳大利亚net程序员 浏览:579
程序员加班难受 浏览:990
如何看服务器品牌 浏览:256
ecy50clp压缩机多少W 浏览:755
mac终端命令怎么保存 浏览:850
微信公众号图片压缩 浏览:440
可以在安卓平板上画画的软件是什么 浏览:438
高盛数字加密 浏览:897