多线程初探(八)

package com.liujunhua.ith02;
/**
 * 线程的等待唤醒机制
 * 两个线程对同一资源进行操作,为保证两者操作资源的独立性,出现了等待唤醒机制。
 * 1.Input线程负责对变量赋值,为了避免在Input在具有CPU执行权时,进行重复的变量赋值动作,
 *   当首次赋值后进行标记,当线程再次赋值的时候,先对标记进行判断,若已经赋值并且该数值还没有
 *   被Output输出,Input线程就等待。即放弃执行权。
 * 2.当Input等待的时候Output就会获得CPU执行权,就会执行相应的输出操作。当完成输出操作后,它将标记为已经操作状态。
 *   当下次执行的时候,如果发现标记已经输出,并且Input没有进行新的赋值,那么就会进入等待状态。
 * 
 * 从而实现了等待唤醒机制。
 * 
 * wait();
 * notify();
 * notifyAll();
 * 
 * 这些方法都使用在同步中,因为要对持有监视器(锁)的线程进行操作。
 * 所以要使用在同步中,因为只有同步才具有锁。
 * 
 * 但是为什么这些操作线程的方法要定义在Object类中呢?
 * 
 * 那是因为这些方法在操作同步中的线程是,都必须要标识他们所操作线程的锁,
 * 只有同一个锁上的被等待的线程,可以被同一个锁上的notify唤醒。
 * 
 * 也就是说,等待和唤醒必须是同一个锁。
 * 
 * 而锁可以是任意对象,所以可以被任意对象调用的方法定义在object类中。
 */
public class Demo01 {

	public static void main(String[] args){
		
		Res r = new Res();

		Input in = new Input(r);
		Output out = new Output(r);

		Thread t1 = new Thread(in);
		Thread t2 = new Thread(out);

		t1.start();
		t2.start();
	}
}

class Res {
	
	private String name;
	private String sex;
	private boolean flag = false;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public boolean isFlag() {
		return flag;
	}
	public void setFlag(boolean flag) {
		this.flag = flag;
	}
	
	public void print(){
		System.out.println(this.name+"........"+this.sex);
	}
}

/**
 * 这里线程锁的创建很有技巧性,如果仅仅是简单的obj对象,肯定是不行的,因为一个obj不可能在两个类里面都可以用。
 * 但此时又需要两个同步代码块用同一个线程锁,这里便采用了两个线程共同操作的Res对象作为线程锁,很好的解决了线程的安全问题。
 */
class Input implements Runnable {

	private Res r;

	Input(Res r) {
		this.r = r;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		int mark = 0;

		while (true) {

			synchronized (r) {
				
				if(r.isFlag())
					try {
						r.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				if (mark == 0) {
					r.setName("mike"); 
					r.setSex("man");
				} else {
					r.setName("丽丽"); 
					r.setSex("女女");
				}
				mark = (mark + 1) % 2;
				
				r.setFlag(true);
				r.notify();
			}

		}
	}

}

class Output implements Runnable {

	private Res r;

	Output(Res r) {
		this.r = r;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while (true) {
			
			synchronized (r) {
				
				if(!r.isFlag()){
					try {
						r.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				r.print();
				r.setFlag(false);
				r.notify();
			}
			
		}
	}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值