线程通信(案例)

什么是线程通信、如何实现?

所谓线程通信就是线程之间相互发送数据,线程通信通常通过共享一个数据的方式实现

线程之间会根据共享数据的情况决定自己改怎么做,以及通知其他线程怎么做

线程通信的常见模型

生产者与消费者模型:生产者线程负责生产数据,消费者线程负责消费数据

要求:生产者线程生产完数据后,唤醒消费者,然后等待自己,消费者消费完数据后,唤醒生产者,然后等待自己

线程通信常用三个方法

void wait() 当前线程等待,直到另一个线程调用notify()或者notiyall() 唤醒自己

void  notify ( ) 唤醒正在等待对象监听器(锁对象) 的单个线程

void notifyAll() 唤醒正在等待对选哪个监听器(锁对象)的多个线程

注意:上述方法应当使用同步锁对象进行调用

案例模拟

一个家庭中,A和B在银行负责存钱,C,D,E在银行中负责取钱。(每次都是整存整取,有钱就不需要存,等待取钱后才可以继续存钱)

账户类(要公用一个账户)

package 线程通信案例;

/**
 * 账户类
 */
public class Account {
	private String cardID;
	private double money;
	/**
	 * @return the cardID
	 */
	public String getCardID() {
		return cardID;
	}
	/**
	 * @param cardID the cardID to set
	 */
	public void setCardID(String cardID) {
		this.cardID = cardID;
	}
	/**
	 * @return the money
	 */
	public double getMoney() {
		return money;
	}
	/**
	 * @param money the money to set
	 */
	public void setMoney(double money) {
		this.money = money;
	}
	public Account(String cardID, double money) {
		super();
		this.cardID = cardID;
		this.money = money;
	}
	public Account() {
		super();
	}
   /**
    * 取钱方法多线程通信需要加锁
    * @param money
    */
	public synchronized void draw(Double money) {
		// TODO Auto-generated method stub
		String name=Thread.currentThread().getName(); //当前线程是谁就获取谁的线程名称
		try {
			if (this.money >= money) {
				//有钱可以取钱
				this.money -= money;
				System.out.println(name + "来取钱" +money+"卡内还剩"+this.money);
				this.notifyAll();
				this.wait();

			} else {

			} 
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	/**
	 * 存钱方法
	 */
public synchronized void  deposit(double money) {
	// TODO Auto-generated method stub
	String name=Thread.currentThread().getName();
	try {
		if (this.money == 0) {
			//没有钱才会存钱
			this.money += money;
			System.out.println(name + "来存钱" +money+"卡内还剩"+ this.money);
			this.notifyAll();
			this.wait();

		} else {
			this.notifyAll();
			this.wait();

		} 
	} catch (Exception e) {
		e.printStackTrace();
	}
	
	
	
}
	
	
	

}

取钱线程

package 线程通信案例;
/**
 * 取钱线程
 * @author ASUS
 *
 */

public class DrawMoneyThread extends Thread {
	Account account;
	//提供一个构造器
	public DrawMoneyThread(Account account ,String name) {
		super(name);
		this.account=account;
	}


	@Override
	public void run() {
		// TODO Auto-generated method stub
		
		while (true) {
			account.draw(10000.0);//整存整取
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		
	}

}

存钱线程

package 线程通信案例;

/**
 * 存钱线程

 */
public class DepositThread  extends Thread{
	Account account;
	public DepositThread(Account account,String name) {
		super(name);
		this.account=account;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		
		while (true) {
			account.deposit(10000.0);
			try {
				Thread.sleep(3000);
		
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		
	}
	
	

}

测试一下

package 线程通信案例;

public class Teat {

	public static void main(String[] args) {
		//创建卡号
		Account ac=new Account("AA_001",0);
		//线程通信要用同一对象
		// 创建两个取钱线程
		new DrawMoneyThread(ac,"取钱A").start();
		new DrawMoneyThread(ac, "取钱B").start();
		//创建3个存钱线程
		new DepositThread(ac,"存钱C").start();
		new DepositThread(ac, "存钱D").start();
		new DepositThread(ac, "存钱E").start();
		

	}

}

 

输出的一直都是(随机的)

存钱C来存钱10000.0卡内还剩10000.0
取钱B来取钱10000.0卡内还剩0.0
存钱E来存钱10000.0卡内还剩10000.0
取钱A来取钱10000.0卡内还剩0.0
存钱C来存钱10000.0卡内还剩10000.0
取钱B来取钱10000.0卡内还剩0.0
存钱C来存钱10000.0卡内还剩10000.0
取钱A来取钱10000.0卡内还剩0.0
存钱C来存钱10000.0卡内还剩10000.0
取钱B来取钱10000.0卡内还剩0.0
存钱D来存钱10000.0卡内还剩10000.0
取钱A来取钱10000.0卡内还剩0.0
存钱C来存钱10000.0卡内还剩10000.0
取钱B来取钱10000.0卡内还剩0.0
存钱D来存钱10000.0卡内还剩10000.0
取钱A来取钱10000.0卡内还剩0.0
存钱C来存钱10000.0卡内还剩10000.0
取钱B来取钱10000.0卡内还剩0.0
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小萌新上大分

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值