线程同步--同步方法_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 线程同步--同步方法

线程同步--同步方法

 2012/3/2 9:59:52  wenbing2610  程序员俱乐部  我要评论(0)
  • 摘要:与同步代码块对应的,Java的多线程安全支持还提供了同步方法,同步方法就是使用synchronized关键字来修饰某个方法,则该方法称为同步方法。对于同步方法而言,无需显示的指定同步监视器,同步方法的同步监视器是this,也就是该对象本身。通过同步方法可以非常方便的将某类变成线程安全的类。为什么要用同步方法?我们知道对于不可变类总是线程安全的,因为它的对象的状态不可改变。但可变对象需要额外的方法来保证其线程安全。例如:在模拟银行取款的用户类就是一个可变类。它的账户余额(假设有这个属性
  • 标签:方法 线程
         与同步代码块对应的,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();
    }
}

发表评论
用户名: 匿名