/*同步方法
对于取钱,当输入要取得钱数,存在计算余额和吐出钱数,由于cpu切换是随机的
在存取之间就有可能存在错误,同时若有好几个人同时取钱,就牵扯到多线程,就要考虑
保护线程,一旦有人进去取钱,其他人都不能进入进行操作,通常可以用
1.用同步方法,用synchronized去修饰方法,例如本例子中用public synchronized void draw(double drawMoney)
2.还可以用同步代码块,synchronized(obj){}去保护线程
3.用lock的方法
*/
第一种方式的例子:
// 这个程序采用的是synchronized方式的锁住线程
/**
* 账号信息:
*
* **/
class Account{
// 余额
private double balance;
// 构造函数
public Account(double balance)
{
super();
this.balance = balance;
//super(name);
}
// getter函数
public double getBalance()
{
return balance;
}
// setter函数
public void setBalance(double balance)
{
this.balance = balance;
}
}
/**
*
* 取钱的操作方法
*
*/
class ATM implements Runnable{
private double dMoney;
private Account a;
public ATM(double dMoney, Account a)
{
super();
this.dMoney = dMoney;
this.a = a;
}
Object o = new Object();
public void run()
{
// 采用同步的方式去,控制线程,一旦进入后就不能让其他的线程进入
synchronized(a){
// 如果余款大于取钱的数就操作
if(a.getBalance() >= dMoney)
{
// 输出要取得钱数
System.out.println(Thread.currentThread().getName()+
"取出的钱数"+dMoney);
// 设置余款
a.setBalance(a.getBalance()-dMoney);
// 打印出余款
System.out.println(Thread.currentThread().getName()+
"还剩"+a.getBalance()+"元");
}
else
{
System.out.println(Thread.currentThread().getName()+
"余额不足,还剩下"+a.getBalance());
}
}
}
}
public class drawMoney {
public static void main(String[] args) {
// 账号钱的初始化
Account aa = new Account(1000);
// 取钱的初始化
ATM atm = new ATM(800, aa);
new Thread(atm, "AA").start();
new Thread(atm, "BB").start();
}
}
第二种方式的例子:
class Account1 {
private double balance ;
public Account1(double balance )
{
super();
this.balance = balance ;
}
public double getBalance()
{
return balance;
}
public void setBalance(double balance)
{
this.balance = balance;
}
// 同步方法
// 取钱
/**
* 同步方法的同步监听器对象: 若该方法是非静态的那么就是this
* 若方法是静态那么就是同步方法所在类的 Class clz = Account2.class;(一份字节码)
*/
public synchronized void draw(double drawMoney )
{
// 能取钱的操作函数
if(balance >= drawMoney)
{
// 取出多少钱
System.out.println(Thread.currentThread().getName()+
"取出多少钱"+drawMoney);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 设置账户余额还有多少
setBalance(balance - drawMoney);
// 余额还有多少
System.out.println(Thread.currentThread().getName()+
"账户的余额是:"+getBalance());
}
else{
System.out.println(Thread.currentThread().getName()+
"账户余额不足,余额为:"+getBalance());
}
}
}
class ATM1 implements Runnable{
// 取得钱数
private double drawMoney;
private Account1 a;
public ATM1(double drawMoney, Account1 a)
{
this.drawMoney = drawMoney;
this.a = a;
}
public void run()
{
a.draw(drawMoney);
}
}
public class synchronizedThread {
public static void main(String [] args)
{
Account1 a = new Account1(1000);
ATM1 atm = new ATM1 (800,a);
// 对于相同的账户,不同的人去取钱
new Thread(atm, "AA").start();
new Thread(atm, "BB").start();
new Thread(atm, "CC").start();
}
}
第三种方式:采用lock的方式
/**
*
*
* java.util.concurrent.locks.Lock接口
* java.util.concurrent.locks.ReentrantLock类
* ReentrantLock,可重入锁,没有同步监听对象
*
*
* 格式:
*
* private final ReentrantLock lock= new ReentrantLock();//创建锁的一个对象
*
* public void m(){
* //进入方法第一件事,上锁
* lock.lock();//获取锁
*
* try{
* //需要同步的代码
* }finally{
* lock.unlock();//解锁,走人
* }
*
*
* }
*
*
*/
import java.util.concurrent.locks.ReentrantLock;
// 创建可重入锁
class Account2
{
private ReentrantLock lock = new ReentrantLock();
private double balance ;
public Account2(double balance)
{
super();
this.balance = balance ;
}
public double getBalance ()
{
return balance;
}
public void setBalance (double balance)
{
this.balance = balance ;
}
public void draw2(double drawMoney)
{
lock.lock();
try{
// 能取钱的操作函数
if(balance >= drawMoney)
{
// 取出多少钱
System.out.println(Thread.currentThread().getName()+
"取出多少钱"+drawMoney);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 设置账户余额还有多少
setBalance(balance - drawMoney);
// 余额还有多少
System.out.println(Thread.currentThread().getName()+
"账户的余额是:"+getBalance());
}
else{
System.out.println(Thread.currentThread().getName()+
"账户余额不足,余额为:"+getBalance());
}
}finally{
lock.unlock();
}
}
}
class ATM2 implements Runnable{
private double drawMoney;
private Account2 a;
public ATM2(Account2 a, double drawMoney)
{
this.a = a;
this.drawMoney = drawMoney;
}
public void run()
{
a.draw2(drawMoney);
}
}
public class lockThread {
public void main(String []args)
{
Account2 a = new Account2(1000);
ATM2 atm = new ATM2(a, 800);
new Thread(atm, "张三").start();
new Thread(atm, "李四").start();
new Thread(atm, "王五").start();
}
}
以上三种方式均可以解决同步问题,就个人感觉而言,用lock的方式好些,好理解好用!