java基础入门-多线程同步浅析-以银行转账为例子
来源:互联网 发布:北京程序员过剩 编辑:程序博客网 时间:2024/05/29 07:37
在说之前先普及一下线程是什么?
线程:说白了就是一个任务片段
进程:是一个具有独立功能的程序关于某个数据集合的一次运行活动,一个进程有一个或者多个线程
线程与进程的本质区别就是有么有数据共享空间,线程之间可以共享数据,进程不可以
下面进入主题:线程间的同步
由于现在业务流程增加,业务节点也增加,使用业务的人员也同时增加,这个时候就不可避免的出现并发问题,多个线程同时访问操作某一个数据单元
我们以银行转账为例说明,下面先上代码:
建立一个银行的类,里面主要包括三个方法,一个是转账,一个是得到现有银行存款总数,一个是得到现在存户数量
public class Bank {private final double[] accounts;public Bank(int n, double initialBalance) {accounts = new double[n];for (int i = 0; i < accounts.length; i++) {accounts[i] = initialBalance;}}public void transfer(int from, int to, double amount) {if (accounts[from] < amount) {return;}System.out.println(Thread.currentThread());accounts[from] -= amount;System.out.printf("%f from %d to %d ", amount, from, to);accounts[to] += amount;System.out.println("total:" + getTotalBalance());}public double getTotalBalance() {double sum = 0d;for (int i = 0; i < accounts.length; i++) {sum += accounts[i];}return sum;}public int getAccountSize() {return accounts.length;}}
下面是转账类,因为需要并发操作,所以实现Runnable接口
public class TransferRunnable implements Runnable {private Bank bank;private int fromAccount = 0;private double maxAmount = 0;public TransferRunnable(Bank b, int fromAccount, double maxAmount) {this.bank = b;this.fromAccount = fromAccount;this.maxAmount = maxAmount;}@Overridepublic void run() {double amount = maxAmount * Math.random();int toAccount = (int) ((int) bank.getAccountSize() * Math.random());bank.transfer(fromAccount, toAccount, amount);try {Thread.sleep((long) (100L * Math.random()));} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
下面是测试类:
public class Test {public static void main(String[] args) {Bank bank = new Bank(100, 1000);for (int i = 0; i < 3; i++) {TransferRunnable transferRunnable = new TransferRunnable(bank, i,1000);Thread thread = new Thread(transferRunnable);thread.start();}}}
输出结果:
Thread[Thread-0,5,main]
Thread[Thread-2,5,main]
Thread[Thread-1,5,main]
430.796266 from 0 to 75
714.274395 from 1 to 88
849.880218 from 2 to 33
total:98435.8453871716
total:99150.11978192833
total:100000.0
我们看上面的结果,特别是最后三行的total总数,发现,第一第二次转账后,总数不对了,仔细观察打印结果,由于并行执行任务,而且中间由于是由cup分配执行顺序,所以我们看到的结果并没有完全按照我们的方法所实现的那样输出出来
由于出现这样的问题,我们引入“锁”的概念,由于这里面是浅析,就不针对锁详细说明,下面我们在bank类里面的转账方法上面加上最简单最常用的锁synchronized,看看结果是怎样:
public class Bank {private final double[] accounts;public Bank(int n, double initialBalance) {accounts = new double[n];for (int i = 0; i < accounts.length; i++) {accounts[i] = initialBalance;}}//加了锁public synchronized void transfer(int from, int to, double amount) {if (accounts[from] < amount) {return;}System.out.println(Thread.currentThread());accounts[from] -= amount;System.out.printf("%f from %d to %d ", amount, from, to);accounts[to] += amount;System.out.println("total:" + getTotalBalance());}public double getTotalBalance() {double sum = 0d;for (int i = 0; i < accounts.length; i++) {sum += accounts[i];}return sum;}public int getAccountSize() {return accounts.length;}}
Thread[Thread-0,5,main]
187.754955 from 0 to 50 total:100000.0
Thread[Thread-1,5,main]
282.138799 from 1 to 90 total:100000.0
Thread[Thread-2,5,main]
217.089515 from 2 to 86 total:100000.00000000001
上面的输出结果基本一致,最后一个结果出现小数问题,主要是由于我数据精度的问题,后续可以通过其他设置来避免。
程序里面由于出现了锁,所以在性能上面不可避免的出现下降,特别是在一些大型程序里面,所以这里面需要根据实际业务所需,把锁的范围锁到比较小的范围,使得性能不会大幅度的下降。
最后我们把上面的东西总结出一个图
- java基础入门-多线程同步浅析-以银行转账为例子
- java基础入门-多线程同步浅析-以银行转账为样例
- JAVA实现银行转账功能
- Spring事务管理的四种方式(以银行转账为例)
- Spring事务管理的四种方式(以银行转账为例)
- Spring事务管理的四种方式(以银行转账为例)
- Java多线程同步---以银行存取钱的过程的简单代码实例
- java多线程-简单转账
- 以关键代码段为例子详细讲解多线程中的同步技术
- java线程浅析[多线程同步]
- Java多线程简单例子,银行存取示例。
- Java模拟银行转账(操作事务)
- java线程同步入门例子
- java 多线程 例子 入门博文一
- 3-3-Java多线程-案例-银行存钱&同步函数
- Java基础--多线程|线程同步
- 最基础的事务 银行转账小事列
- JAVA 同步函数以this为锁
- new/delete 与 malloc/free 的区别是什么?
- Mac下OpenCV3.0和OpenCV2.x自由切换
- Golang for循环
- ATS日志格式中的Squid-和Netscape-格式的缓存结果码
- 调用有道词典查词
- java基础入门-多线程同步浅析-以银行转账为例子
- c++11 使用c++风格的cast: static_cast<type>(expression) const_cast<type> dynamic_cast reinterpret_cast
- NBA史上薪水最高球员排行榜
- 安卓手机开发的学习资料
- C++的内存模型
- 深度解读:都是顶薪为什么浓眉远超卡哇伊?
- vim编辑器颜色主题color scheme
- SQL Server中的DBlink的使用
- 《编程导论(Java)·3.2.4 循环语句》