多线程之间的友好通信-等待唤醒机制

线程之间的友好通信等待唤醒机制(wait\notify)
wait:调用wait方法,是当前线程从运行状态转变为阻塞状态,使用wait方法必须要有锁的支持,当前线程必须要有调用该方法的对象的监视器(也就是说该线程使用的同步锁必须与调用wait方法的对象保持一致)。
notify:唤醒拥有同一个监听器的其他同步线程(当然只会唤醒一个,由JVM决定);
错误代码:
class SubThread implements Runnable {

	private Demo demo;

	public SubThread(Demo demo) {
		this.demo = demo;
	}

	@Override
	public synchronized void run() {//错误原因:使用的是同步方法,该方法锁是:this
		while (true) {
			try {
				if (demo.flag) {
					demo.wait();//而这里却是demo对象
				}

			} catch (InterruptedException e) {
				//
			}
			for (int i = 0; i < 10; i++) {
				demo.i++;
				System.out.println(Thread.currentThread().getName() + "----"
						+ demo.i);
			}

			demo.flag = true;
			demo.notify();
		}

	}

}
原因分析:
wait方法和notify方法,用于同一个监听器的同步线程,而同步方法的锁是当前对象,也就是SubThread对象。
wait和notify方法与同步方法使用的不是同一个锁,因此报如下错误:

Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
	at java.lang.Object.notify(Native Method)
	at com.day27.test.SubThread.run(Test2.java:67)
	at java.lang.Thread.run(Thread.java:619)



解决方法:使用同步代码块
如下:
class Test{

	public static void main(String[] args) {
		Demo demo = new Demo();
		SubThread sub = new SubThread(demo);
		Thread thread = new Thread(sub);
		thread.start();

		while (true) {
			synchronized (demo) {//由于两个线程同步操作dmeo对象,因此两个线程的同步锁必须是同一个对象并且是demo
				if (!demo.flag) {//当flag为false时,阻塞当前线程
					try {
						demo.wait();//由dmeo对象调用wait方法
					} catch (InterruptedException e) {
						// 
					}
				}

				for (int i = 0; i < 100; i++) {
					demo.i++;
					System.out.println(Thread.currentThread().getName()
							+ "----" + demo.i);
				}

				demo.flag = false;//执行完主线程,设置flag为false
				demo.notify();//唤醒拥有同一个对象demo的监听器的其他同步线程
			}

		}

	}
}

class Demo {
	public boolean flag;//线程友好通信的标志
	public int i;//两个线程共享的数据
}

class SubThread implements Runnable {

	private Demo demo;

	public SubThread(Demo demo) {
		this.demo = demo;
	}

	@Override
	public void run() {
		while (true) {
			synchronized (demo) {//同步锁对象
				try {
					if (demo.flag) {//当flag为true时,使子线程处于阻塞状态
						demo.wait();//调用wait方法,是当前线程处于阻塞状态
					}

				} catch (InterruptedException e) {
					//
				}
				for (int i = 0; i < 10; i++) {
					demo.i++;
					System.out.println(Thread.currentThread().getName()
							+ "----" + demo.i);
				}

				demo.flag = true;//当子线程执行完成后,设置flag为true
				demo.notify();//唤醒拥有同一个监视器的其他同步线程
			}
		}

	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值