所谓线程通信就是线程之间相互发送数据,线程通信通常通过共享一个数据的方式实现
线程之间会根据共享数据的情况决定自己改怎么做,以及通知其他线程怎么做
生产者与消费者模型:生产者线程负责生产数据,消费者线程负责消费数据
要求:生产者线程生产完数据后,唤醒消费者,然后等待自己,消费者消费完数据后,唤醒生产者,然后等待自己
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