一.该面试题主要考察多线程中的synchronized或者Lock的使用

 * 线程同步 :使用同步方法,实现线程同步
 * 同步synchronized方法的对象监视锁为this,当前对象
 * 多个线程使用同一把锁,如果线程安全必需确保:多个线程使用的是同一个this对象(Runnable适用于共享同一对象[如:this],如果Thread继承就会有问题[推荐使用Runnable])
 * 所有访问此对象方法的线程都在方法外等待,都会判断同步锁,降低效率,但确保线程安全问题
 * java的每个对象都有一个内置锁,当用synchronized关键字修饰方法时,内置锁会保护整个方法。在调用该方法前,线程需要获得内置锁,否则就处于阻塞状

synchronized关键字也可以修饰静态方法,此时如果调用该静态方法,将会锁住整个类

此例子中使用synchronized关键字:

private synchronized void makeWithdraw(int amount){...}

二.上代码

BankAccount.java

 1 public class BankAccount {
 2     //余额
 3     private int balance = 500;
 4     //查询
 5     public int getBalance(){
 6         return balance;
 7     }
 8     //取款
 9     public void withdraw(int amount){
10         balance = balance - amount;
11     }
12     //存款
13     public void deposit(int amount){
14         balance = balance + amount;
15     }
16 }

SyncMethod.java

 1 /**
 2  * 此线程类实现Runnable接口
 3  * 线程同步 :使用同步方法,实现线程同步
 4  * 同步synchronized方法的的对象监视锁为this,当前对象
 5  * 多个线程使用同一把锁,如果线程安全必需确保:多个线程使用的是同一个this对象
 6  * 所有访问此对象方法的线程都在方法外等待,都会判断同步锁,降低效率,但确保线程安全问题
 7  * */
 8 public class SyncMethod implements Runnable {
 9     // 所有Thread多线程线程都共享Runnable(接口对象)和account对象
10     private BankAccount account = new BankAccount();
11     @Override
12     public void run() {
13         for (int i = 0; i < 5; i++) {// 总共取款5次
14             makeWithdraw(100); // 每次取款100
15             if (account.getBalance() < 0) {
16                 System.out.println("" + Thread.currentThread().getName()+ "   透支了!");
17             }
18         }
19     }
20
21     /**
22      * makeWithdraw 账户取款
23      * @param amount取款金额
24      * 打印log记录取款过程
25      * */
26     private synchronized void makeWithdraw(int amount){
27         if(account.getBalance() >= amount){//如果余额足够则取款
28             System.out.println("" + Thread.currentThread().getName() + "   准备取款!");
29             try {
30                 Thread.sleep(500);
31             } catch (InterruptedException e) {
32                 System.out.println(Thread.currentThread().getName() + "   准备取款,等待0.5s线程中断!" + e.getMessage());
33             }
34             account.withdraw(amount);
35             System.out.println("" + Thread.currentThread().getName() + "   完成" + amount + "取款!余额为" + account.getBalance());
36         }else{//余额不足则提示
37             System.out.println("" + "余额不足以支付" + Thread.currentThread().getName() + amount + "   的取款,余额为" + account.getBalance());
38         }
39     }
40 }

TreadSyncTest.java

 1 public class TreadSyncTest {
 2
 3     /*
 4         Junit不适合多线程并发测试。
 5         因为线程还在激活状态的时候,Junit已经执行完成。
 6         在Junit的TestRunner中,它没有被设计成搜寻Runnable实例,
 7         并且等待这些线程发出报告,它只是执行它们并且忽略了它们的存在。
 8         综上,不可能在Junit中编写和维护多线程的单元测试。
 9      */
10     /*
11         @Test
12         public void test() {
13         }
14     */
15
16     public static void main(String[] args) {
17         //实现Runnable:所有Thread多线程线程都共享Runnable(接口对象)
18         //NoSync target =new NoSync();
19         SyncMethod target = new SyncMethod();
20         //创建罗密欧和朱丽叶两个线程实现取款(同时)
21         Thread romeoThread = new Thread(target);
22         romeoThread.setName("罗密欧");
23         Thread julietThread = new Thread(target);
24         julietThread.setName("朱丽叶");
25         //调用Thread对象的start()方法,启动线程,执行run()方法(OS)
26         romeoThread.start();
27         julietThread.start();
28     }
29 }

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
正常运行结果1:
罗密欧   准备取款!
罗密欧   完成100取款!余额为400
罗密欧   准备取款!
罗密欧   完成100取款!余额为300
罗密欧   准备取款!
罗密欧   完成100取款!余额为200
罗密欧   准备取款!
罗密欧   完成100取款!余额为100
罗密欧   准备取款!
罗密欧   完成100取款!余额为0
余额不足以支付朱丽叶100   的取款,余额为0
余额不足以支付朱丽叶100   的取款,余额为0
余额不足以支付朱丽叶100   的取款,余额为0
余额不足以支付朱丽叶100   的取款,余额为0
余额不足以支付朱丽叶100   的取款,余额为0.
正常运行结果2:
罗密欧   准备取款!
罗密欧   完成100取款!余额为400
罗密欧   准备取款!
罗密欧   完成100取款!余额为300
罗密欧   准备取款!
罗密欧   完成100取款!余额为200
罗密欧   准备取款!
罗密欧   完成100取款!余额为100
朱丽叶   准备取款!
朱丽叶   完成100取款!余额为0
余额不足以支付朱丽叶100   的取款,余额为0
余额不足以支付朱丽叶100   的取款,余额为0
余额不足以支付朱丽叶100   的取款,余额为0
余额不足以支付罗密欧100   的取款,余额为0
余额不足以支付朱丽叶100   的取款,余额为0
正常运行结果3:
罗密欧   准备取款!
罗密欧   完成100取款!余额为400
罗密欧   准备取款!
罗密欧   完成100取款!余额为300
罗密欧   准备取款!
罗密欧   完成100取款!余额为200
朱丽叶   准备取款!
朱丽叶   完成100取款!余额为100
朱丽叶   准备取款!
朱丽叶   完成100取款!余额为0
余额不足以支付朱丽叶100   的取款,余额为0
余额不足以支付朱丽叶100   的取款,余额为0
余额不足以支付朱丽叶100   的取款,余额为0
余额不足以支付罗密欧100   的取款,余额为0
余额不足以支付罗密欧100   的取款,余额为0

如果不用synchronized关键字的结果:

罗密欧   准备取款!
朱丽叶   准备取款!
朱丽叶   完成100取款!余额为300
罗密欧   完成100取款!余额为300
罗密欧   准备取款!
朱丽叶   准备取款!
朱丽叶   完成100取款!余额为100
朱丽叶   准备取款!
罗密欧   完成100取款!余额为100
罗密欧   准备取款!
罗密欧   完成100取款!余额为0
余额不足以支付罗密欧100   的取款,余额为0
余额不足以支付罗密欧100   的取款,余额为0
朱丽叶   完成100取款!余额为-100
朱丽叶   透支了!
余额不足以支付朱丽叶100   的取款,余额为-100
朱丽叶   透支了!
余额不足以支付朱丽叶100   的取款,余额为-100
朱丽叶   透支了!
本文转自SummerChill博客园博客,原文链接:http://www.cnblogs.com/DreamDrive/p/7726072.html,如需转载请自行联系原作者

写出线程同步相关的方法,以银行账号存储款为例相关推荐

  1. [js] 对`a == (‘1‘||‘2‘||‘3‘) ? false : true`写法进行改进,写出你优化后的方法

    [js] 对a == ('1'||'2'||'3') ? false : true写法进行改进,写出你优化后的方法 ![1,2,3].includes(+a) or !['1', '2', '3']. ...

  2. ARCGIS 出图的时候写出微克每立方米的方法

    写出微克每立方米的方法 1.直接将 输入后 (µg/m3) 就可以出来.

  3. java线程同步的各种方法

    原子操作:由一组相关的操作完成,这些操作可能会操纵与其它的线程共享的资源,为了保证得到正确的运算结果,一个线程在执行原子操作其间,应该采取其他的措施使得其他的线程不能操纵共享资源. 原子操作:根据Ja ...

  4. java多线程学习二、安全与不安全示例:12306买票和银行取钱、java内存模型、内存可见性、线程同步块和方法

    文章目录 前言 1. 什么是块,分为几种 2. 静态块与构造块的区别 一. 举例说明:并发情况下,线程不安全 1. 示例1:unsafe12306取票 2. 示例2:unsafe银行取钱 二.线程不安 ...

  5. 教你几个写出原创文章的小方法

    网站中最重要的东西就是原创.而且是大量的原创信息才会使得你网站有一个好的排名,在这里肯定有很多朋友问,哪来这么多大量的原创信息呢. 1. 把外国人的东西翻译成自己的东西 呵呵,这点其实是最有效果的,人 ...

  6. windows下线程同步的常见方法:CreateEvent和SetEvent及WaitForSingleObject windows下常见锁的实现 EnterCriticalSection

    windows下我们常用的线程同步的方法是 事件 首先介绍CreateEvent是创建windows事件的意思,作用主要用在判断线程退出,程锁定方面. CreateEvent 函功能描述:创建或打 ...

  7. 线程同步的各种方法汇总

    目录 互斥锁 读写锁 自旋锁 条件变量 屏障 互斥锁 两种状态: (1)加锁,pthread_mutex_lock() . (2)不加锁,pthread_mutex_unlock() . 读写锁 三种 ...

  8. 纯css写出tips的几种方法

    最近在项目中用到了很多的小tips,之前都是随便找一套UI控件拿过来用一下就算完事了,一直也没有去管这个东西究竟是怎么搞出来的,只是大概知道这个东西怎么实现的,但是一套UI毕竟是太大了,tips也就是 ...

  9. 页面jquery调试的一个宝贵经验(类似于Eclipse中的写出一个对象点它的方法时候用alt加/可以跳出来它所有的方法)...

    假如你现在还在为自己的技术担忧,假如你现在想提升自己的工资,假如你想在职场上获得更多的话语权,假如你想顺利的度过35岁这个魔咒,假如你想体验BAT的工作环境,那么现在请我们一起开启提升技术之旅吧,详情 ...

  10. 如何写出高效的软件测试用例?微信朋友圈动态发送为例

    编写一份好的测试用例需要:充分的需求分析能力 + 理论及经验加持. 但这并不意味着,没测试经验.分析能力弱就不能写好用例,还是有方法可循的.作为混迹测试职场 10 年的老人,给大家分享一些用例编写的心 ...

最新文章

  1. NYOJ 762 第k个互质数(二分 + 容斥)
  2. Shiro <shiro:hasPermission >标签不生效,shiro权限不生效原因
  3. 08-百度ai语音合成
  4. 动态规划训练8 [E - Multiplication Puzzle POJ1651]
  5. python treeview文本自动换行显示_在tkinter.ttk.Treeview列中设置文本格式
  6. css中margin:0 auto没作用
  7. [JLOI2015]城池攻占 左偏树
  8. 二叉树的层序遍历 二叉树
  9. md5加密算法使用流程
  10. Flink Watermark 机制浅析(透彻)
  11. UnFlow:具有双向普查损失的光流的无监督学习
  12. 怎么用显卡计算_教师:课程表的时间怎么用公式自动计算?
  13. 安卓开发快速学习!330页PDF,10万字的知识点总结,附面试题答案
  14. 数字图像处理(MATLAB)(第二版) 冈萨雷斯 学习笔记
  15. java打星星_java初学打印星星以及九九乘法表
  16. Lightroom 中照片的修改信息储存在哪了?
  17. C语言·一年有3.156*10^7秒,输入年龄,显示对应秒数。
  18. 银河娱乐集团 2020 年第三季度未经审核之财务数据
  19. 数据量大的情况下,WPS excel如何批量间隔一行或多行进行插入空行操作
  20. 特斯拉Model S 引爆电动车市狂鸣

热门文章

  1. Atitit 减少财政支出之减少通讯支出 解决方案attilax总结
  2. Atitit 快速开发的推荐技术标准化 规范 大原则
  3. Atitit usbQb212 oo 面向对象封装的标准化与规范解决方案java c# php js
  4. Atiti. Php Laravel 5.1 环境搭建以及  error 排除
  5. WebAssembly的未来:潜在新特性一览
  6. Rust: flat_map、filter_map、for_each
  7. (转)一个由自由职业者建立的量化对冲基金
  8. Julia : csv =hdf5
  9. Julia : Array !, [1,2] !=[1 2]'
  10. php 判断来源 微信客户端_常见WebShell客户端的流量特征及检测思路