多線程同步案例三(家庭消費環境)

============================================

模擬場景:家庭消費多線程

  1. 家庭成員:父親、母親、孩子
  2. 家庭有一個公用的金錢賬戶
  3. 父親:負責掙錢
  4. 兒子:打遊戲
  5. 母親:購物消費

要求:

  • 不能負債消費!

============================================

一、實體類

Family.java

package net.xiaof.thread2.entity;

/**
 * 家庭實體
 * 
 * @author XIAO
 */
public class Family {

	private Father father; // 父親
	private Mother mother;// 母親
	private Child child;// 孩子
	private double accountMoney;// 家庭賬戶金錢

	public Family() {

	}

	public Father getFather() {
		return father;
	}

	public void setFather(Father father) {
		this.father = father;
	}

	public Mother getMother() {
		return mother;
	}

	public void setMother(Mother mother) {
		this.mother = mother;
	}

	public Child getChild() {
		return child;
	}

	public void setChild(Child child) {
		this.child = child;
	}

	public double getAccountMoney() {
		return accountMoney;
	}

	public void setAccountMoney(double accountMoney) {
		this.accountMoney = accountMoney;
	}

}

Father.java

package net.xiaof.thread2.entity;

/**
 * 父親實體
 * 
 * @author XIAO
 */
public class Father {

	private String name; // 姓名
	private Family family;// 家庭對象

	public Father() {

	}

	public Father(String name, Family family) {
		super();
		this.name = name;
		this.family = family;
	}

	/**
	 * 賺錢
	 * @param money 金額
	 */
	public void earnMoney(double money) {
		synchronized (this.family) {
			System.out.println(this.name+"充值前,家庭賬戶金錢:"+this.family.getAccountMoney());
			this.family.setAccountMoney(this.family.getAccountMoney()+money);
			System.out.println(this.name+"充值後,家庭賬戶金錢:"+this.family.getAccountMoney());
		}
	}
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Family getFamily() {
		return family;
	}

	public void setFamily(Family family) {
		this.family = family;
	}

}

Mother.java

package net.xiaof.thread2.entity;

/**
 * 母親實體
 * 
 * @author XIAO
 */
public class Mother {

	private String name; // 姓名
	private Family family;// 家庭對象

	public Mother() {

	}

	public Mother(String name, Family family) {
		super();
		this.name = name;
		this.family = family;
	}

	/**
	 * 購物
	 * 
	 * @param money
	 *            消費金額
	 */
	public void shopping(double money) {
		synchronized (this.family) {
			System.out.println(this.name + "購物前,家庭賬戶金錢:" + this.family.getAccountMoney());
			if (this.family.getAccountMoney() >= money) {
				this.family.setAccountMoney(this.family.getAccountMoney() - money);
				System.out.println("        " + this.name + "消費金錢:" + money);
			} else {
				System.out.println("☹  !賬戶金額不足,請【" + this.name + "】暫停消費");
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Family getFamily() {
		return family;
	}

	public void setFamily(Family family) {
		this.family = family;
	}

}

Child.java

package net.xiaof.thread2.entity;

/**
 * 孩子實體
 * 
 * @author XIAO
 */
public class Child {

	private String name; // 姓名
	private Family family;// 家庭對象

	public Child() {

	}

	public Child(String name, Family family) {
		super();
		this.name = name;
		this.family = family;
	}

	/**
	 * 玩遊戲
	 * 
	 * @param money
	 *            消費金額
	 */
	public void playGames(double money) {
		synchronized (this.family) {
			System.out.println(this.name + "打遊戲前,家庭賬戶金錢:" + this.family.getAccountMoney());
			if (this.family.getAccountMoney() >= money) {
				this.family.setAccountMoney(this.family.getAccountMoney() - money);
				System.out.println("        " + this.name + "消費金錢:" + money);
			} else {
				System.out.println("☹  !賬戶金額不足,請【" + this.name + "】暫停消費");
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Family getFamily() {
		return family;
	}

	public void setFamily(Family family) {
		this.family = family;
	}

}


二、線程任務類

【注】:此處測試,由於while循環沒有結束條件(或結束標誌),所以在添加同步(synchronized)時,應添加在while(true){ }內部中,否則 模擬時,只要有一個線程進行家庭消費(減金額),其他消費線程則不能進入。

FatherTask.java

package net.xiaof.thread2.task;

import net.xiaof.thread2.entity.Father;

/**
 * 父親線程任務類:父親賺錢
 * 
 * @author XIAO
 *
 */
public class FatherTask implements Runnable {

	private Father father;

	public FatherTask(Father father) {
		this.father = father;
	}

	@Override
	public void run() {
		while (true) {
			this.father.earnMoney(30); // 消費30
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

}

MotherTask.java

package net.xiaof.thread2.task;

import net.xiaof.thread2.entity.Mother;

/**
 * 母親線程任務類:母親購物花錢
 * 
 * @author XIAO
 *
 */
public class MotherTask implements Runnable {

	private Mother mother;

	public MotherTask(Mother mother) {
		this.mother = mother;
	}

	@Override
	public void run() {
		while (true) {
			this.mother.shopping(10); // 消費10
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

}

ChildTask.java

package net.xiaof.thread2.task;

import net.xiaof.thread2.entity.Child;

/**
 * 孩子線程任務類:孩子玩遊戲花錢
 * 
 * @author XIAO
 *
 */
public class ChildTask implements Runnable {

	private Child child;

	public ChildTask(Child child) {
		this.child = child;
	}

	@Override
	public void run() {
		while (true) {
			this.child.playGames(10); // 消費10
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

}


三、測試類

package net.xiaof.thread2.test;

import net.xiaof.thread2.entity.Child;
import net.xiaof.thread2.entity.Family;
import net.xiaof.thread2.entity.Father;
import net.xiaof.thread2.entity.Mother;
import net.xiaof.thread2.task.ChildTask;
import net.xiaof.thread2.task.FatherTask;
import net.xiaof.thread2.task.MotherTask;

/**
 * 測試類
 * @author XIAO
 */
public class TestDemo {
	
	public static void main(String[] args) {
		//實例化一個家庭
		Family family = new Family();
		Father father = new Father("父親", family);
		Mother mother = new Mother("母親", family);
		Child child = new Child("孩子", family);
		
		//開啓多線程
		FatherTask fatherTask = new FatherTask(father);
		Thread t1 = new Thread(fatherTask);
		t1.start();
		
		MotherTask motherTask = new MotherTask(mother);
		Thread t2 = new Thread(motherTask);
		t2.start();
		
		ChildTask childTask = new ChildTask(child);
		Thread t3 = new Thread(childTask);
		t3.start();
	}
	
}


三、控制檯輸出

父親充值前,家庭賬戶金錢:0.0
父親充值後,家庭賬戶金錢:30.0
孩子打遊戲前,家庭賬戶金錢:30.0
        孩子消費金錢:10.0
母親購物前,家庭賬戶金錢:20.0
        母親消費金錢:10.0
孩子打遊戲前,家庭賬戶金錢:10.0
        孩子消費金錢:10.0
母親購物前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【母親】暫停消費
孩子打遊戲前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【孩子】暫停消費
母親購物前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【母親】暫停消費
孩子打遊戲前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【孩子】暫停消費
母親購物前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【母親】暫停消費
孩子打遊戲前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【孩子】暫停消費
母親購物前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【母親】暫停消費
孩子打遊戲前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【孩子】暫停消費
母親購物前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【母親】暫停消費
孩子打遊戲前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【孩子】暫停消費
母親購物前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【母親】暫停消費
孩子打遊戲前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【孩子】暫停消費
父親充值前,家庭賬戶金錢:0.0
父親充值後,家庭賬戶金錢:30.0
母親購物前,家庭賬戶金錢:30.0
        母親消費金錢:10.0
孩子打遊戲前,家庭賬戶金錢:20.0
        孩子消費金錢:10.0
母親購物前,家庭賬戶金錢:10.0
        母親消費金錢:10.0
母親購物前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【母親】暫停消費
孩子打遊戲前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【孩子】暫停消費
母親購物前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【母親】暫停消費
孩子打遊戲前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【孩子】暫停消費
母親購物前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【母親】暫停消費
孩子打遊戲前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【孩子】暫停消費
母親購物前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【母親】暫停消費
孩子打遊戲前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【孩子】暫停消費
母親購物前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【母親】暫停消費
父親充值前,家庭賬戶金錢:0.0
父親充值後,家庭賬戶金錢:30.0
孩子打遊戲前,家庭賬戶金錢:30.0
        孩子消費金錢:10.0
母親購物前,家庭賬戶金錢:20.0
        母親消費金錢:10.0
孩子打遊戲前,家庭賬戶金錢:10.0
        孩子消費金錢:10.0
孩子打遊戲前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【孩子】暫停消費
母親購物前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【母親】暫停消費
孩子打遊戲前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【孩子】暫停消費
母親購物前,家庭賬戶金錢:0.0
☹  !賬戶金額不足,請【母親】暫停消費
孩子打遊戲前,家庭賬戶金錢:0.0
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章