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

java多线程ifwait

发布时间:2022-11-26 04:42:56

java多线程有几种状态

新建(new)

新建一个线程的对象。

可运行(runable)

线程对象创建后,其他线程调用该线程的start方法。或者该线程位于可运行线程池中等待被线程调用,已获取cpu的使用权。

运行(running)

可运行的线程获取了cpu的使用权,执行程序代码/

阻塞(block)

由于某些原因该线程放弃了cpu的使用权。停止执行。除非线程进入可运行的状态,才会有机会获取cpu的使用权。

1. 等待阻塞:运行中的线程执行wait方法,这时候该线程会被放入等待队列。

2. 同步阻塞:运行中的线程获取同步锁,如果该同步锁被别的线程占用,这个线程会成被放入锁池,等待其他线程释放同步锁。

3. 其他阻塞:运行的线程执行sleep或者join方法这个线程会成为阻塞状态。当sleep超时,join等待线程终止,该线程会进入可运行状态。

死亡(dead)

线程run mian 执行完毕后,或者因为某些异常产生退出了 run 方法,该线程的生命周期结束。

② java线程,wait()方法怎么把自己给停掉了

Thread.currentThread().wait() //引用当前的线程

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

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

④ java中if (){ wait();}else{},假如判断完if后wait了,notify后如何运行

1、如果一个线程调用了某个对象的wait方法,那么该线程进入到该对象的等待池中(并且已经将锁释放), 如果未来的某一时刻,另外一个线程调用了相同对象的notify方法或者notifyAll方法, 那么该等待池中的线程就会被唤起,然后进入到对象的锁池里面去获得该对象的锁, 如果获得锁成功后,那么该线程就会沿着wait方法之后的路径继续执行。注意是沿着wait方法之后 2.如果没有直接性的调用同类里的其他接口,或者返回,结束等java关键字,代码还是得往下执行的。

⑤ JAVA线程wait()方法问题

应该使用wait(),wait 方法的解释是
Causes current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.

举个例子:
比如你有一个Depository 类的对象 d ,然后线程A要访问d的addLast()方法,
因为这个addLast()方法时synchronized 所以线程A进入的时候就给这个对象d 加上锁,其它线程不允许访问,当执行到wait()时,线程A就会先打开对象A的锁,并在对象d 外面排队等待。

对于IllegalMonitorStateException,我的理解是:
一个对象的wait()方法只能在此对象的同步方法中被调用,意思是,这个对象在wait前是被加了锁的。

你将addLast方法的synchronized 去掉运行也会抛出这样的异常。

所以说你用wait()就可以了。
Thread.currentThread().wait();这句话调用的是当前线程对象的wait()方法,
当前线程对象没有被加锁。所以出错。

个人理解,仅供参考,希望能帮到你

⑥ 如何在 Java 中正确使用 wait,notify 和 notifyAll

我们先来了解一下为什么要使用wait,notify


首先看一下以下代码:

synchronized(a){
...//1
synchronized(b){
}
}
synchronized(b){
...//2
synchronized(a){
}
}

假设现在有两个线程, t1 线程运行到了//1 的位置,而 t2 线程运行到了//2 的位置,接

下来会发生什么情况呢?

此时, a 对象的锁标记被 t1 线程获得,而 b 对象的锁标记被 t2 线程获得。对于 t1 线程

而言,为了进入对 b 加锁的同步代码块, t1 线程必须获得 b 对象的锁标记。由于 b 对象的锁标记被 t2 线程获得, t1 线程无法获得这个对象的锁标记,因此它会进入 b 对象的锁池,等待 b 对象锁标记的释放。而对于 t2 线程而言,由于要进入对 a 加锁的同步代码块,由于 a 对象的锁标记在 t1 线程手中,因此 t2 线程会进入 a 对象的锁池。

此时, t1 线程在等待 b 对象锁标记的释放,而 t2 线程在等待 a 对象锁标记的释放。由

于两边都无法获得所需的锁标记,因此两个线程都无法运行。这就是“死锁”问题。


在 Java 中,采用了 wait 和 notify 这两个方法,来解决死锁机制。

首先,在 Java 中,每一个对象都有两个方法: wait 和 notify 方法。这两个方法是定义

在 Object 类中的方法。对某个对象调用 wait()方法,表明让线程暂时释放该对象的锁标记。

例如,上面的代码就可以改成:

synchronized(a){
...//1
a.wait();
synchronized(b){
}
}
synchronized(b){
...//2
synchronized(a){
...
a.notify();
}
}

这样的代码改完之后,在//1 后面, t1 线程就会调用 a 对象的 wait 方法。此时, t1 线程

会暂时释放自己拥有的 a 对象的锁标记,而进入另外一个状态:等待状态。

要注意的是,如果要调用一个对象的 wait 方法,前提是线程已经获得这个对象的锁标

记。如果在没有获得对象锁标记的情况下调用 wait 方法,则会产生异常。

由于 a 对象的锁标记被释放,因此, t2 对象可以获得 a 对象的锁标记,从而进入对 a

加锁的同步代码块。在同步代码块的最后,调用 a.notify()方法。这个方法与 wait 方法相对应,是让一个线程从等待状态被唤醒。

那么 t2 线程唤醒 t1 线程之后, t1 线程处于什么状态呢?由于 t1 线程唤醒之后还要在

对 a 加锁的同步代码块中运行,而 t2 线程调用了 notify()方法之后,并没有立刻退出对 a 锁的同步代码块,因此此时 t1 线程并不能马上获得 a 对象的锁标记。因此,此时, t1 线程会在 a 对象的锁池中进行等待,以期待获得 a 对象的锁标记。也就是说,一个线程如果之前调用了 wait 方法,则必须要被另一个线程调用 notify()方法唤醒。唤醒之后,会进入锁池状态。线程状态转换图如下:

classConsumerextendsThread{
privateMyStackms;
publicConsumer(MyStackms){
this.ms=ms;
}
publicvoidrun(){
while(true){
//为了保证push和pop操作的完整性
//必须加synchronized
synchronized(ms){
//如果栈空间已满,则wait()释放ms的锁标记
while(ms.isEmpty()){
try{
ms.wait();
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
charch=ms.pop();
System.out.println("Pop"+ch);
ms.notifyAll();
}
//push之后随机休眠一段时间
try{
sleep((int)Math.abs(Math.random()*100));
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
}
//生产者
classProcerextendsThread{
privateMyStackms;
publicProcer(MyStackms){
this.ms=ms;
}
publicvoidrun(){
while(true){
//为了保证push和pop操作的完整性
//必须加synchronized
synchronized(ms){
//如果栈空间已满,则wait()释放ms的锁标记
while(ms.isFull()){
try{
ms.wait();
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
ms.push('A');
System.out.println("pushA");
ms.notifyAll();
}
//push之后随机休眠一段时间
try{
sleep((int)Math.abs(Math.random()*200));
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
}
//主方法中,启用生产者与消费者两个线程
publicclassTestWaitNotify{
publicstaticvoidmain(String[]args){
MyStackms=newMyStack();
Threadt1=newProcer(ms);
Threadt2=newConsumer(ms);
t1.start();
t2.start();
}
}

部分代码纯手打,望采纳~

⑦ 如何在 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解决生产者消费者问题,我几乎可以肯定他们中的大多数都会无所适从或者犯下一些错误,例如在错误的地方使用
synchronized 关键词,没有对正确的对象使用wait,或者没有遵循规范的代码方法。说实话,这个问题对于不常使用它们的程序员来说确实令人感觉比较头疼。
第一个问题就是,我们怎么在代码里使用wait()呢?因为wait()并不是Thread类下的函数,我们并不能使用
Thread.call()。事实上很多Java程序员都喜欢这么写,因为它们习惯了使用Thread.sleep(),所以他们会试图使用wait()

来达成相同的目的,但很快他们就会发现这并不能顺利解决问题。正确的方法是对在多线程间共享的那个Object来使用wait。在生产者消费者问题中,这
个共享的Object就是那个缓冲区队列。
第二个问题是,既然我们应该在synchronized的函数或是对象里调用wait,那哪个对象应该被synchronized呢?答案是,那个

你希望上锁的对象就应该被synchronized,即那个在多个线程间被共享的对象。在生产者消费者问题中,应该被synchronized的就是那个
缓冲区队列。(我觉得这里是英文原文有问题……本来那个句末就不应该是问号不然不太通……)
永远在循环(loop)里调用 wait 和 notify,不是在 If 语句
现在你知道wait应该永远在被synchronized的背景下和那个被多线程共享的对象上调用,下一个一定要记住的问题就是,你应该永远在
while循环,而不是if语句中调用wait。因为线程是在某些条件下等待的——在我们的例子里,即“如果缓冲区队列是满的话,那么生产者线程应该等
待”,你可能直觉就会写一个if语句。但if语句存在一些微妙的小问题,导致即使条件没被满足,你的线程你也有可能被错误地唤醒。所以如果你不在线程被唤

醒后再次使用while循环检查唤醒条件是否被满足,你的程序就有可能会出错——例如在缓冲区为满的时候生产者继续生成数据,或者缓冲区为空的时候消费者
开始小号数据。所以记住,永远在while循环而不是if语句中使用wait!我会推荐阅读《Effective Java》,这是关于如何正确使用wait和notify的最好的参考资料。
基于以上认知,下面这个是使用wait和notify函数的规范代码模板:
// The standard idiom for calling the wait method in Java synchronized (sharedObject) { while (condition) { sharedObject.wait(); // (Releases lock, and reacquires on wakeup) } // do action based upon condition e.g. take or put into queue }
就像我之前说的一样,在while循环里使用wait的目的,是在线程被唤醒的前后都持续检查条件是否被满足。如果条件并未改变,wait被调用之前notify的唤醒通知就来了,那么这个线程并不能保证被唤醒,有可能会导致死锁问题。
Java wait(), notify(), notifyAll() 范例
下面我们提供一个使用wait和notify的范例程序。在这个程序里,我们使用了上文所述的一些代码规范。我们有两个线程,分别名为
PRODUCER(生产者)和CONSUMER(消费者),他们分别继承了了Procer和Consumer类,而Procer和
Consumer都继承了Thread类。Procer和Consumer想要实现的代码逻辑都在run()函数内。Main线程开始了生产者和消费
者线程,并声明了一个LinkedList作为缓冲区队列(在Java中,LinkedList实现了队列的接口)。生产者在无限循环中持续往
LinkedList里插入随机整数直到LinkedList满。我们在while(queue.size ==
maxSize)循环语句中检查这个条件。请注意到我们在做这个检查条件之前已经在队列对象上使用了synchronized关键词,因而其它线程不能在
我们检查条件时改变这个队列。如果队列满了,那么PRODUCER线程会在CONSUMER线程消耗掉队列里的任意一个整数,并用notify来通知
PRODUCER线程之前持续等待。在我们的例子中,wait和notify都是使用在同一个共享对象上的。

⑧ 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为锁的线程解锁等待.
这样,就可以使程序的两个线程来回切换了.

⑨ Java多线程中await和wait的区别

  1. 调用await/wait的时候却释放了其获取的锁并阻塞等待。

  2. await/wait,它会一直阻塞在条件队列之上,之后某个线程调用对应的notify/signal方法,才会使得await/wait的线程回到就绪状态,也是不一定立即执行。

  3. await/wait方法必须放在同步块里面,否则会产生运行时异常。

  4. wait方法是Object类的,await方法是Condition显示条件队列的。

⑩ java多线程怎样让一个线程睡眠

可以使用sleep()方法。

sleep()方法拥有一个参数,它控制睡眠的长短,以毫秒计算。sleep()方法会抛出InterruptedException,所以一定在try-catch块里面使用它。

示例代码如下:

{
inti=0;

publicstaticvoidmain(String[]args){
Aa1=newA();
Aa2=newA();
a1.run();
a2.run();
}

publicvoidrun(){
while(++i<=100){
System.out.println(i);
try{
Thread.sleep(50);
}catch(Exceptione){
e.printStackTrace();
}
}
}
}

注意,sleep()方法并不保证线程醒来后进入运行,只能保证它进入就绪状态。

阅读全文

与java多线程ifwait相关的资料

热点内容
sift算法harris算法 浏览:241
python命令行模式 浏览:459
新妈妈韩国电影中的辅导老师是谁 浏览:388
php邮箱验证代码 浏览:404
光猫伪装命令 浏览:175
安卓高端机为什么都用曲屏 浏览:419
老电影大全 战争片 浏览:971
有没有小电影得网址网站 浏览:378
奥特曼电影排行榜前十名 浏览:580
安卓光遇账号过期怎么找回 浏览:476
现金宝宝app在哪里能下载 浏览:277
二战女教师慰安妇电影 浏览:270
传说对决录像在哪个文件夹 浏览:136
不用充钱就能看电视剧的网站 浏览:562
卧式空气压缩机 浏览:137
合川排课管理系统源码 浏览:439
女主被用铁链囚禁的小说 浏览:196
两个小时的爱情电影 浏览:864
php电商下单并发处理 浏览:242