(三十一)java多线程二
因为线程在执行的过程中具有一定的不确定性,在并发的时候就会出现安全问题,因此一般需要采取一定的措施来保证线程的安全,同步代码块就是其中一种方式。
以下是模拟银行取钱的多线程小例子,两个都能确保安全,但是有一种却更好一些。
例1:
packagedemo1;
/**
*
模拟两个人同时取一个账户的钱,必须只能有一个人能取成功
*@authortuzongxun
*
*/
publicclass ThreadTest6 {
publicstaticvoidmain(String[]args)
{
// 创建一个用户账户
Account account = newAccount("tu", 1000);
// 创建两个线程模拟取钱
GetMoney get1 = newGetMoney("甲", account,
600);
GetMoney get2 = newGetMoney("乙", account,
500);
// 启动线程
get1.start();
get2.start();
}
}
/**
* 模拟账户
* @authortuzongxun
*
*/
class Account {
/**
* 账户名
*/
private StringaccountNum;
/**
* 账户余额
*/
private Doublemoney;
publicAccount(String accountNum,double money) {
this.accountNum = accountNum;
this.money = money;
}
public StringgetAccountNum() {
returnaccountNum;
}
publicvoidsetAccountNum(StringaccountNum) {
this.accountNum = accountNum;
}
public DoublegetMoney() {
returnmoney;
}
publicvoidsetMoney(Double money) {
this.money = money;
}
}
classGetMoneyextends
Thread {
privatefinaldoublenum;
privatefinal Accountaccount;
publicGetMoney(String name,Account account,double num) {
super(name);
this.num = num;
this.account = account;
}
@Override
publicvoidrun() {
/**
* 这里锁住了整个用户对象,所以先开始的线程会锁定对象,另一个不能获得对象,无法结束
* 只有当操作账户的线程结束后,另一个线程才能结束
*/
synchronized (account) {
if (account.getMoney() >num) {
account.setMoney(account.getMoney() -num);
System.out.println("用户(
" + this.getName()
+ " )取钱成功,取了("
+ account.getAccountNum()
+ ")的账户:" +num
+ "元");
System.out.println("账户余额:"
+ account.getMoney() +"元");
}else {
System.out.println("用户(
" + this.getName()
+ " )取钱失败");
System.out.println("账户余额:"
+ account.getMoney() +"元");
}
}
}
}
例2:
packagedemo1;
/**
* 模拟两个人同时取一个账户的钱,必须只能有一个人能取成功
* @authortuzongxun
*
*/
publicclass ThreadTest7 {
publicstaticvoidmain(String[]
args) {
Account1 account = newAccount1("tu", 1000);
newGetMoney1("甲", account, 600).start();
newGetMoney1("乙", account, 500).start();
}
}
/**
* 模拟账户
* @authortuzongxun
*
*/
class Account1 {
private StringaccountName;
privatedoublebalance;
publicAccount1(StringaccountName,double balance) {
this.accountName = accountName;
this.balance = balance;
}
public StringgetAccountName() {
returnaccountName;
}
publicvoidsetAccountName(StringaccountName) {
this.accountName = accountName;
}
publicdoublegetBalance() {
returnbalance;
}
publicvoidsetBalance(double balance) {
this.balance = balance;
}
/**
* 这里只是锁住了取钱的方法,所以有可能第一个线程运行一半时,第二个开始运行并可能先结束
*但是就算第一个后结束,第二个线程依然取钱失败。
*@param money
* @return
*/
publicsynchronizeddoublegetMondy(double
money) {
if (balance > money) {
balance -= money;
return 1;
} else {
return -1;
}
}
};
classGetMoney1extends
Thread {
privatefinal Account1account;
privatefinaldoublemoney;
publicGetMoney1(String name,Account1 account,double money) {
super(name);
this.account = account;
this.money = money;
}
@Override
publicvoidrun() {
double getMoney =account.getMondy(money);
if (getMoney > 0){
System.out.println(this.getName()
+ "取款成功,取了"
+ account.getAccountName() +"账户:"
+ money
+ "元");
System.out.println("账户余额:"
+ account.getBalance());
} else {
System.out.println(this.getName()
+ "取款失败");
System.out.println("账户余额:"
+ account.getBalance());
}
}
}
(三十一)java多线程二的更多相关文章
- “全栈2019”Java第三十一章:二维数组和多维数组详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- java 多线程二
java 多线程一 java 多线程二 java 多线程三 java 多线程四 线程中断: /** * Created by root on 17-9-30. */ public class Test ...
- java多线程二之线程同步的三种方法
java多线程的难点是在:处理多个线程同步与并发运行时线程间的通信问题.java在处理线程同步时,常用方法有: 1.synchronized关键字. 2.Lock显示加锁. 3.信号量Se ...
- 从零开始学习Java多线程(二)
前面已经简单介绍进程和线程,为后续学习做铺垫.本文讨论多线程传参,Java多线程异常处理机制. 1. 多线程的参数传递 在传统开发过程中,我们习惯在调用函数时,将所需的参数传入其中,通过函数内部逻辑处 ...
- Java多线程(二) —— 深入剖析ThreadLocal
对Java多线程中的ThreadLocal类还不是很了解,所以在此总结一下. 主要参考了http://www.cnblogs.com/dolphin0520/p/3920407.html 中的文章. ...
- Java多线程(二) 多线程的锁机制
当两条线程同时访问一个类的时候,可能会带来一些问题.并发线程重入可能会带来内存泄漏.程序不可控等等.不管是线程间的通讯还是线程共享数据都需要使用Java的锁机制控制并发代码产生的问题.本篇总结主要著名 ...
- java多线程(二)-Runnable和Thread
Java在顺序性语言的基础上提供了多线程的支持.Java的线程机制是抢占式的.这表示调度机制会周期的中断线程,将上下文切换到另一个线程,从而为每个线程都提供时间片.(与抢占式多线程对应的是 协作式多线 ...
- java多线程(二)之实现Runnable接口
一.java多线程方式2: 实现Runnable接口 好处:a. 可以避免由于java单继承带来的局限性. b. 适合多个相同的程序的代码去处理同一个资源的情况, 把线程与程序的代码, 数据有效分离, ...
- java多线程(二)
线程的阻塞状态: 参考java多线程(一)多线程的生命周期图解,多线程的五种状态. 1.1 join(),如果在A线程体里面执行了B线程的join()方法,那么A线程阻塞,直到B线程生命周期结 ...
随机推荐
- php应用pack函数转unicode为utf8
因为时常用到json_encode去处理数据,json_encode在处理字符串遇上中文时,会把中文转换成\u5371这种格式的字符串,如果想让它能正常显示中文,则可以用pack打包函数进行处理. 以 ...
- spring boot + vue + element-ui全栈开发入门——开篇
最近经常看到很多java程序员朋友还在使用Spring 3.x,Spring MVC(struts),JSP.jQuery等这样传统技术.其实,我并不认为这些传统技术不好,而我想表达的是,技术的新旧程 ...
- 使用hbase小结
背景 hbase中一张表的rowkey定义为时间戳+字符串 需求 根据时间戳和列簇中某列的值为"abc",导出一天内的数据到excel中. 使用FilterList FilterL ...
- RMI基础篇
远程方法调用(Remote Method Invocation,RMI)从JDK1.1就已经实现,它大大增强了Java开发分布式应用的能力. RMI可以实现通过网络完成不同JVM间的通信,不仅可以传递 ...
- 如何用JavaScript制作循环图形
[图题思路] 1.确定图形一共几行,即为外层的循环的次数 2.确定每行有几种元素,代表有几个内层循环 3.确定每种元素的个数,即为每个内层循环的次数Tips:通常,找出每种元 ...
- s5pv210 的启动
1.开发板已启动从0x0获取数据(内部64k的硬盘,里面含有三星固化的BL0段代码),将其读到a8软核中,进行运算,主要用于初始化时钟,96k的内部IRAM.并负责 指定启动设备(通常为外部硬盘),从 ...
- shell脚本实现anisble客户端脚本分发和密钥授权配置
##############################Deploy ansible client shell######################## echo "start d ...
- Linux-安装FFmpeg
FFmpeg官网:http://www.ffmpeg.org 官网介绍 FFmpeg is the leading multimedia framework, able to decode, enco ...
- C#仪器数据文件解析-PDF文件
不少仪器工作站输出的数据报告文件为PDF格式,PDF格式用于排版打印,但不易于数据解析,因此解析PDF数据需要首先读取到PDF文件中的文本内容,然后根据内容规则解析有意义的数据信息. C#解析PDF文 ...
- spring core 与 context理解
Spring core是核心层,拥有这BeanFactory这个强大的工厂,是所有bean的管理器: 而spring context是上下文运行环境,基于spring core之上的一个架构, 它之上 ...