java判断线程是否wait_java多线程wait()方法必须放在while循环里面的原因探析

1、写一个包子生产消费案例:一次生产或消费一个包子,有包子就消费,没有就生产。(部分代码参考传智播客刘意2015Java基础视频讲义)

1.1 写一个Baozi.class,包含main()方法,用来测试

packagecom.oy.demo3;/** 包子生产消费案例:一次生产或消费一个包子,有包子就消费,没有就生产。*/

public classBaozi {//默认是flag,表示没有包子,需要生产线程来生产包子;如果是true,说明有包子,需要消费端来消费包子。

public booleanflag;//计数,当前在生产或消费第n个包子

public int count = 0;public static voidmain(String[] args) {//创建共享对象

Baozi s = newBaozi();//在外界把共享对象创建出来,通过构造方法传递给其他的类。这样st、gt1、gt2就共享s对象。

SetThread st = newSetThread(s);

GetThread gt1= newGetThread(s);

GetThread gt2= newGetThread(s);//线程类

Thread t1 = newThread(st);

Thread t2= newThread(gt1);

Thread t3= newThread(gt2);//启动线程

t1.start();

t2.start();

t3.start();

}

}

1.2 生产包子的线程类 SetThread.class

packagecom.oy.demo3;public class SetThread implementsRunnable {privateBaozi s;publicSetThread(Baozi s) {this.s =s;

}

@Overridepublic voidrun() {while (true) {synchronized(s) {//判断有没有

if (s.flag) { //生产端,有就等待

try{

System.out.println("生产端:等待。。。");

s.wait();//等待,并且立即释放锁。将来醒过来的时候,是从这里醒过来的

System.out.println("生产端:醒过来了。。。");

}catch(InterruptedException e) {

e.printStackTrace();

}

}//开始生产

s.count++;

System.out.println("生产第" + s.count + "包子。。。");//生产完后,修改标记为true

s.flag = true;//唤醒线程

s.notifyAll();

System.out.println("==========开始抢CPU的执行权==========");

}

}

}

}

1.3 消费包子的线程类 GetThread.class

packagecom.oy.demo3;public class GetThread implementsRunnable {privateBaozi s;publicGetThread(Baozi s) {this.s =s;

}

@Overridepublic voidrun() {while (true) {synchronized(s) {while (!s.flag) { //消费端,没有就等待

try{

System.out.println(Thread.currentThread().getName()+ "消费端:等待。。。");

s.wait();//等待,并且立即释放锁。将来醒过来的时候,是从这里醒过来的

System.out.println(Thread.currentThread().getName() + "消费端:醒过来了。。。");

}catch(InterruptedException e) {

e.printStackTrace();

}

}//开始消费

System.out.println(Thread.currentThread().getName() + "消费第" + s.count + "个包子");//消费完了,修改标记为false

s.flag = false;//唤醒线程

s.notifyAll();

System.out.println("==========开始抢CPU的执行权==========");

}

}

}

}

2、测试结果(只选择了控制台打印的部分结果):

==========开始抢CPU的执行权==========

生产端:等待。。。

Thread-2消费端:醒过来了。。。

Thread-2消费第6806个包子

==========开始抢CPU的执行权==========

Thread-2消费端:等待。。。

Thread-1消费端:醒过来了。。。

Thread-1消费端:等待。。。

生产端:醒过来了。。。

生产第6807包子。。。

==========开始抢CPU的执行权==========

3、对测试结果的分析:

3.1 首先明确,生产端开启了一个线程,消费端开启了两个线程。

3.2 Thread-2消费第6806个包子,然后唤醒等待的线程;然后3个线程开始抢CPU的执行权,Thread-2消费端线程抢到了,但是此时没有包子了,所以等待;

3.3 然后,Thread-1消费端线程抢到了执行权,在原来wait()方法的地方醒过来,执行wait()方法后面的代码System.out.println(Thread.currentThread().getName() + "消费端:醒过来了。。。");然后继续while循环判断,由于此时没有包子,所以等待。如果把while改成if,就不会判断是否有包子,之间执行后面的代码消费包子,此时并没有包子了,这就产生了错误(同一个包子被消费了两次)。

3.4 综上所述:wait()方法套在while循环中,线程下次醒过来后会继续进行循环,判断条件是否满足,满足就重新等待。

3.5 由于生产端只开启了一个线程,所以将wait()方法套在if代码块中也是可以的,当然使用while也可以。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值