java基础入门-多线程同步浅析-以银行转账为样例
来源:互联网 发布:pic单片机开发环境iar 编辑:程序博客网 时间:2024/05/28 22:12
在说之前先普及一下线程是什么?
线程:说白了就是一个任务片段
进程:是一个具有独立功能的程序关于某个数据集合的一次执行活动。一个进程有一个或者多个线程
线程与进程的本质差别就是有么有数据共享空间。线程之间能够共享数据。进程不能够
以下进入主题:线程间的同步
因为如今业务流程添加。业务节点也添加。使用业务的人员也同一时候添加。这个时候就不可避免的出现并发问题,多个线程同一时候訪问操作某一个数据单元
我们以银行转账为例说明,以下先上代码:
建立一个银行的类,里面主要包含三个方法,一个是转账,一个是得到现有银行存款总数,一个是得到如今存户数量
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基础入门-多线程同步浅析-以银行转账为例子
- Spring事务管理的四种方式(以银行转账为例)
- Spring事务管理的四种方式(以银行转账为例)
- Spring事务管理的四种方式(以银行转账为例)
- JAVA实现银行转账功能
- Java多线程同步---以银行存取钱的过程的简单代码实例
- java多线程-简单转账
- java线程浅析[多线程同步]
- Java模拟银行转账(操作事务)
- 动态规划基础入门(以数字三角形为例)
- 3-3-Java多线程-案例-银行存钱&同步函数
- Java基础--多线程|线程同步
- 最基础的事务 银行转账小事列
- JAVA 同步函数以this为锁
- 银行账号同步多线程处理
- 关于多线程同步的几点疑问(以CRITICAL_SECTION 为例)
- 以同一张银行卡取钱为例,演示同步多线程方法
- mysql数据库忘记密码时如何修改
- python&Django&mariadb&Apache&mod_wsgi 环境部署
- homebrew安装及常用命令
- linux中安装mysql,如何开启远程访问权限
- 策略梯度(Policy Gradients)的理解
- java基础入门-多线程同步浅析-以银行转账为样例
- mysql查询重复数据的语句
- 【POJ 3984】迷宫问题
- Redis 并发 锁 竞争锁问题
- 微信小程序导航
- java 格式输出
- 将cordova.js放到服务器端调不起android插件
- 走近人脸检测——基本流程
- Java中多线程并发处理方式