因为线程在执行的过程中具有一定的不确定性,在并发的时候就会出现安全问题,因此一般需要采取一定的措施来保证线程的安全,同步代码块就是其中一种方式。

以下是模拟银行取钱的多线程小例子,两个都能确保安全,但是有一种却更好一些。

例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多线程二的更多相关文章

  1. “全栈2019”Java第三十一章:二维数组和多维数组详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  2. java 多线程二

    java 多线程一 java 多线程二 java 多线程三 java 多线程四 线程中断: /** * Created by root on 17-9-30. */ public class Test ...

  3. java多线程二之线程同步的三种方法

          java多线程的难点是在:处理多个线程同步与并发运行时线程间的通信问题.java在处理线程同步时,常用方法有: 1.synchronized关键字. 2.Lock显示加锁. 3.信号量Se ...

  4. 从零开始学习Java多线程(二)

    前面已经简单介绍进程和线程,为后续学习做铺垫.本文讨论多线程传参,Java多线程异常处理机制. 1. 多线程的参数传递 在传统开发过程中,我们习惯在调用函数时,将所需的参数传入其中,通过函数内部逻辑处 ...

  5. Java多线程(二) —— 深入剖析ThreadLocal

    对Java多线程中的ThreadLocal类还不是很了解,所以在此总结一下. 主要参考了http://www.cnblogs.com/dolphin0520/p/3920407.html 中的文章. ...

  6. Java多线程(二) 多线程的锁机制

    当两条线程同时访问一个类的时候,可能会带来一些问题.并发线程重入可能会带来内存泄漏.程序不可控等等.不管是线程间的通讯还是线程共享数据都需要使用Java的锁机制控制并发代码产生的问题.本篇总结主要著名 ...

  7. java多线程(二)-Runnable和Thread

    Java在顺序性语言的基础上提供了多线程的支持.Java的线程机制是抢占式的.这表示调度机制会周期的中断线程,将上下文切换到另一个线程,从而为每个线程都提供时间片.(与抢占式多线程对应的是 协作式多线 ...

  8. java多线程(二)之实现Runnable接口

    一.java多线程方式2: 实现Runnable接口 好处:a. 可以避免由于java单继承带来的局限性. b. 适合多个相同的程序的代码去处理同一个资源的情况, 把线程与程序的代码, 数据有效分离, ...

  9. java多线程(二)

    线程的阻塞状态: 参考java多线程(一)多线程的生命周期图解,多线程的五种状态.     1.1 join(),如果在A线程体里面执行了B线程的join()方法,那么A线程阻塞,直到B线程生命周期结 ...

随机推荐

  1. Single-Pass Stereo Rendering for HoloLens——HoloLens的单程立体渲染

    原文网站:https://docs.unity3d.com/Manual/SinglePassStereoRenderingHoloLens.html Single-Pass Stereo Rende ...

  2. Designing Data-Intensive Applications

    下面是这本书序言中的大部分内容,本人的英文水平有限,有理解不到位的地方还请大家指教,这算是自己对这本书的读书笔记和总结. 数据是当今系统设计中许多挑战的中心,一些难以解决的问题如系统的可扩展性,一致性 ...

  3. c# 实现mysql事务

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  4. python os模块实用函数

    os.sep可以取代操作系统特定的路径分隔符.windows下为 “\\” os.name字符串指示你正在使用的平台.比如对于Windows,它是'nt',而对于Linux/Unix用户,它是'pos ...

  5. 生成模型(generative model)与判别模型(discriminative model)的区别

    监督学习可以分为生成方法与判别方法,所学到的模型可以分为生成模型与判别模型. 生成模型 生成模型由数据学习联合概率分布\(P(X,Y)\),然后求出条件概率分布\(P(Y|X)\)作为预测的模型,即生 ...

  6. BZOJ 3239: Discrete Logging [BGSG]

    裸题 求\(ind_{n,a}b\),也就是\(a^x \equiv b \pmod n\) 注意这里开根不能直接下取整 这个题少了一些特判也可以过... #include <iostream& ...

  7. POJ 3608 Bridge Across Islands [旋转卡壳]

    Bridge Across Islands Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10455   Accepted: ...

  8. Retrofit 实践

    Retrofit是一套RESTful架构的Android(Java)客户端实现,基于注解,提供JSON to POJO(Plain Ordinary Java Object,简单Java对象),POJ ...

  9. client / page / offset / screen X / Y

    1.clientX / clientY 相对于可视窗口左上角,不包括菜单栏与滚动条 2.pageX / pageY 相对于网页左上角,不包括菜单栏,包括滚动条 3.offsetX / offsetY ...

  10. Office 365 机器人(Bot)开发入门指南 (新篇)

    最近在整理书稿时,发现我在2017年7月份写的这篇 Office 365 机器人(Bot)开发入门 的内容,因为相关平台的升级,已经完全不能体现当前的开发过程,所以我再专门写一篇新的开发入门指南给有兴 ...