本文实例讲述了Java使用同步方法解决银行取钱的安全问题。分享给大家供大家参考,具体如下:

一 点睛

与同步代码块对应,Java的多线程安全支持还提供了同步方法,同步方法就是使用synchronized关键字来修饰某个方法,则该方法称为同步方法。对于synchronized修饰的实例方法(非static方法)而言,无须显示指定同步监视器,同步方法的同步监视器是this,也就是调用该方法的对象。

通过使用同步方法可以非常方便地实现线程安全的类,线程安全的类具有如下特征。

该类的对象可以被多个线程安全地访问。

每个线程调用该对象的任意方法之后都将得到正确的结果。

每个线程调用该对象的任意方法之后,该对象状态依然保持合理状态。

不可变类总是线程安全的,因为它的对象状态不可改变;但可变对象需要额外的方法来保证其线程安全。

二 代码

1 定义一个账户类

public class Account

{

// 封装账户编号、账户余额两个成员变量

private String accountNo;

private double balance;

public Account(){}

// 构造器

public Account(String accountNo , double balance)

{

this.accountNo = accountNo;

this.balance = balance;

}

// accountNo的setter和getter方法

public void setAccountNo(String accountNo)

{

this.accountNo = accountNo;

}

public String getAccountNo()

{

return this.accountNo;

}

// 因此账户余额不允许随便修改,所以只为balance提供getter方法,

public double getBalance()

{

return this.balance;

}

// 提供一个线程安全draw()方法来完成取钱操作

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()

+ "取钱失败!余额不足!");

}

}

// 下面两个方法根据accountNo来重写hashCode()和equals()方法

public int hashCode()

{

return accountNo.hashCode();

}

public boolean equals(Object obj)

{

if(this == obj)

return true;

if (obj !=null

&& obj.getClass() == Account.class)

{

Account target = (Account)obj;

return target.getAccountNo().equals(accountNo);

}

return false;

}

}

2 定义一个取钱线程

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方法来执行取钱

// 同步方法的同步监视器是this,this代表调用draw()方法的对象。

// 也就是说:线程进入draw()方法之前,必须先对account对象的加锁。

account.draw(drawAmount);

}

}

3 测试主类

public class DrawTest

{

public static void main(String[] args)

{

// 创建一个账户

Account acct = new Account("1234567" , 1000);

// 模拟两个线程对同一个账户取钱

new DrawThread("甲" , acct , 800).start();

new DrawThread("乙" , acct , 800).start();

}

}

三 运行结果

乙取钱成功!吐出钞票:800.0

余额为: 200.0

甲取钱失败!余额不足!

四 说明

1 增加了代码取钱的draw()方法,并使用了synchronized关键字修饰该方法,把该方法变成了同步方法,该同步方法的同步监视器是this,因此对于同一个Account账户而言,任意时刻只能有一个线程获得对Account对象的锁定,然后进入draw()方法执行取钱操作——这样也可以保证多个线程并发取钱的线程安全。

2 可变类的线程安全是以减低程序的运行效率作为代价的,为了减少线程安全带来的负面影响,程序可以采用如下策略:

不要对线程安全类的所有方法都进行同步,只对那些会改变竞争资源(竞争资源也就是共享资源)的方法进行同步。例如上面Account类中的accountNo实例变量就无须同步,所以程序只对draw()方法进行了同步控制。

如果可变类有两种运行环境:单线程运行环境和多线程运行环境,则应该为该可变类提供两种版本,即线程安全版本和线程不安全版本。在单线程环境中使用线程不安全版本以保证性能,在多线程中环境中使用线程安全版本。

3 JDK提供的StringBuilder和StringBuffer就是为了照顾单线程环境和多线程环境提供的类,在单线程环境中应该使用StringBuilder类来保证较好的性能,当需要保证多线程安全时,就应该使用StringBuffer。

更多java相关内容感兴趣的读者可查看本站专题:《Java进程与线程操作技巧总结》、《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总》

希望本文所述对大家java程序设计有所帮助。

java银行安全性_Java使用同步方法解决银行取钱的安全问题案例分析相关推荐

  1. Java培训总结:过滤器链的实现方法、配置和案例分析

    今天小千给大家分享的是Java培训总结:过滤器链的实现方法.配置和案例分析. 过滤器能够对网站中的各种内容进行过滤(页面.Servlet.图片.文件),可以在网站内容请求和响应时进行一些操作,完成一些 ...

  2. ATM柜员机JAVA课程设计_JAVA课程设计报告银行ATM机系统.doc

    JAVA课程设计报告银行ATM机系统 Java课程设计报告 题 目 银行ATM机系统 所在院系 软件学院 学生姓名 金磊 专 业 R机械+软件 班 级 R机械094 学 号 2011年 7 月 15日 ...

  3. java银行取款_Java写简单的银行取钱系统

    按ctrl+a 选中所有的代码删除,再复制下面的代码输入即可 import java.util.Scanner; public class 简单的银行取钱系统 //class的名字可以自己新建和这个一 ...

  4. java 线程安全性_Java线程安全性问题摘要_Power Node Java Academy的组织

    在Java内存模型上 不同的平台,内存模型不同,但是jvm内存模型规范是统一的. 实际上,Java的多线程并发问题最终将反映在Java的内存模型中. 所谓的线程安全无非是控制多个线程对多个资源的有序访 ...

  5. 设计一个银行账户类,可以存钱、取钱、查钱、获取开户日期 内有测试类

    class bank 银行账户类 /* * 1.设计一个银行账户类,* 其中包括:账户信息:账号.姓名.开户时间.身份证号码.账户上的金额等成员.* 有:存款方法.取款方法.显示开户时间的方法.获得账 ...

  6. java虚拟机进程_Java虚拟机详解(七)------虚拟机监控和分析工具(1)——命令行...

    通过前面的几篇博客,我们介绍了Java虚拟机的内存分配以及内存回收等理论知识,了解这些知识对于我们在实际生产环境中提高系统的运行效率是有很大的帮助的.但是话又说回来,在实际生产环境中,线上项目正在运行 ...

  7. java线程安全性_Java并发-线程安全性

    1.什么是线程安全性? 在线程安全性的定义中,最核心的就是正确性.当多线程访问调用某个类时,线程之间不会出现错误的交互,不管运行时线程如何交替执行,并且在主调代码不需要任何同步或协同,这个类都能表现出 ...

  8. java comparable排序_Java使用Comparable解决排序问题

    本文实例讲述了Java使用Comparable解决排序问题的方法.分享给大家供大家参考.具体实现方法如下: 一次举重竞赛的比赛规则是:选手的成绩以成功举起的总重量来排序,举起总重量多的排在前面:当举起 ...

  9. java php安全性_java和php安全性有什么不同

    java和php安全性有什么不同 发布时间:2020-11-09 11:56:07 来源:亿速云 阅读:96 作者:小新 小编给大家分享一下java和php安全性有什么不同,相信大部分人都还不怎么了解 ...

最新文章

  1. 谁说C语言和C+太难?没前途?谬论!
  2. jupyter笔记本_如何为Jupyter笔记本电脑设置PySpark
  3. [爬虫学习笔记]C# 使用 ScrapySharp 并行下载天涯图片
  4. 关于OnPaint、FormPaint会不停的触发 触发多次的情形---讨论总结
  5. [vue] vue中什么是递归组件?举个例子说明下?
  6. Win10 IIS本地部署网站运行时图片和样式不正常?
  7. 给文章添加目录的方法
  8. 个人如何注册小程序账号,亲测有效!
  9. 7-15 城市间紧急救援 (10 分)
  10. Ajax (部分二:prototype.js代码后半部分)自己做的,总结页面向后台传Form值、单个值和后台向前台传一个或是一组值...
  11. 用shedlock实现分布式定时任务锁
  12. kubernetes 一个窗口可以使用kubectl 另一个窗口不可以The connection to the server localhost:8080 was refused - did you
  13. 知道域名差服务器系统,对DNS域名系统的抓包分析
  14. CCNA学习资料简介
  15. 山东大学暑期实训-饮食健康管理系统设计与实现(十三)
  16. atom n270 cpu linux,继续改造ATOM N270增加千兆口自制软路由
  17. 【小万出生记——第0篇】想做一款机械手
  18. 小白如何利用自媒体做引流推广?
  19. 电商用户价值分析——基于RFM模型、KMeans聚类
  20. 一招教会你语音转文字转换器怎么使用

热门文章

  1. EOS将发布的官方EVM怎么样?
  2. 加拿大安省哪个高中注重计算机,安省高中体制,你真的了解吗
  3. OOAD-设计模式(四)结构型模式之适配器、装饰器、代理模式
  4. js实现点击复制功能
  5. 基于tensorflow的mnist数据集手写字体分类level-1
  6. 钉钉小程序实现富文本编辑
  7. 数学之美,美在将复杂问题简化——《数学之美》读后感
  8. 非对称加密RSA算法原理及实际应用场景
  9. Java14发布,16大新特性,代码更加简洁明快
  10. python调取高德api_Python调用高德API实现批量地址转经纬度并写入表格的功能