线程同步--同步方法

与同步代码块对应的,Java的多线程安全支持还提供了同步方法,同步方法就是使用synchronized关键字来修饰某个方法,则该方法称为同步方法。对于同步方法而言,无需显示的指定同步监视器,同步方法的同步监视器是this,也就是该对象本身。
通过同步方法可以非常方便的将某类变成线程安全的类。为什么要用同步方法?我们知道对于不可变类总是线程安全的,因为它的对象的状态不可改变。但可变对象需要额外的方法来保证其线程安全。例如:在模拟银行取款的用户类就是一个可变类。它的账户余额(假设有这个属性)这个属性就是可变的,当两个线程同时修改用户账户这个类的账户余额属性时,程序就会出现异常。可以把用户账户的取钱方法设置为同步方法来保证线程安全。用同步方法模拟银行取款可建立以下类:【1】用户类【2】取款类【3】测试类。

【1】用户类Account代码如下:

package com.thread.synchronizedMethod;

/**
* 用户类
*
* @author wwb
*
*/
public class Account {
private String accountNo;
private double balance;

public Account() {
}

public synchronized void draw(double drawAmount) {
// 账户余额大于取钱数目
if (balance >= drawAmount) {
// 吐出钞票
System.out.println(Thread.currentThread().getName() + "取钱成功!吐出钞票:"
+ drawAmount);
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
// 修改余额
balance -= drawAmount;
System.out.println("\t余额为: " + balance);
} else {
System.out.println(Thread.currentThread().getName() + "取钱失败!余额不足!");
}
}

public Account(String accountNo, double balance) {
this.accountNo = accountNo;
this.balance = balance;
}

public void setAccountNo(String accountNo) {
this.accountNo = accountNo;
}

public String getAccountNo() {
return this.accountNo;
}

public double getBalance() {
return this.balance;
}

public int hashCode() {
return accountNo.hashCode();
}

public boolean equals(Object obj) {
if (obj != null && obj.getClass() == Account.class) {
Account target = (Account) obj;
return target.getAccountNo().equals(accountNo);
}
return false;
}
}

【2】取款类DrawThread代码:

package com.thread.synchronizedMethod;

/**
* 取款类
*
* @author wwb
*
*/
public class DrawThread extends Thread
{
//模拟用户账户
private Account account;
//当前取钱线程所希望取的钱数
private double drawAmount;

public DrawThread(String name , Account account ,
double drawAmount)
{
super(name);
this.account = account;
this.drawAmount = drawAmount;
}

//当多条线程修改同一个共享数据时,将涉及到数据安全问题。
public void run()
{
account.draw(drawAmount);
}
}
【3】测试类TestDraw代码:

package com.thread.synchronizedMethod;

/**
* 测试类
*
* @author wwb
*
*/
public class TestDraw
{
public static void main(String[] args)
{
//创建一个账户
Account acct = new Account("1234567" , 1000);
//模拟两个线程对同一个账户取钱
new DrawThread("甲" , acct , 800).start();
new DrawThread("乙" , acct , 800).start();
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值