Java线程同步
来源:互联网 发布:php 直播 编辑:程序博客网 时间:2024/06/11 04:06
Java线程同步
使用synchronized来同步方法
一个模拟银行账户取款增款的例子
该例子共有4个类,分别是Account(账户类),Bank(取款),Company(增款),Client(用户)。Bank类会模拟100次取款,每次1000,Company类会模拟100次增款,每次1000。用户初始账户为1000,所以正确情况应该是余额依然为1000。
下面是Account源代码:
package com.zk;public class Account { /** 余额 **/ private double balance; /** 查询余额 **/ public double getBalance(){ return balance; } /** 设置余额 **/ public void setBalance(double balance){ this.balance = balance; } /** 增加余额 **/ public synchronized void addAmount(double amount){ double tmp = balance; try{ Thread.sleep(10); }catch(InterruptedException e){ e.printStackTrace(); } tmp += amount; balance = tmp; } /** 减少余额**/ public synchronized void substractAmount(double amount){ double tmp = amount; try{ Thread.sleep(10); }catch(InterruptedException e){ e.printStackTrace(); } tmp -= amount; balance = tmp; }}
Bank代码:
package com.zk;/** 从银行中取款 **/public class Bank implements Runnable { private Account account; public Bank(Account account){ this.account = account; } @Override public void run() { for(int i=0; i<100; ++i){ account.substractAmount(1000); } }}
Company代码:
package com.zk;/** 公司会发工资 **/public class Company implements Runnable { private Account account; public Company(Account account){ this.account = account; } @Override public void run() { for(int i=0; i<100; ++i){ account.addAmount(1000); } }}
Client代码:
package com.zk;public class Client { public static void main(String[] args) { //初始账户:1000元 Account account = new Account(); account.setBalance(1000); Company company = new Company(account); Thread companyThread = new Thread(company); Bank bank = new Bank(account); Thread bankThread = new Thread(bank); System.out.printf("Account: Initial Balance: %f.\n", account.getBalance()); //启动两个线程:模拟100次存款(每次1000),100次取款(每次1000) companyThread.start(); bankThread.start(); try { //使用join方法来等待两个线程结束(die) companyThread.join(); bankThread.join(); System.out.printf("Account: Final Balance: %f.\n.", account.getBalance()); } catch (InterruptedException e) { e.printStackTrace(); } }}
多次运行结果如下:
通过Thread.sleep(10)
我们来模拟取款增款时的一个延时。
在去掉addAmount()
和substractAmount()
前面的关键字synchronized
以后,当我们再次执行,会发现出现了错误的结果,而且每次结果不一样。这是因为JVM是不保证线程执行顺序,所以每次运行结果不一样。
而当我们添加上synchronized
关键字的时候,这个时候当线程A正在执行Account
类中标有synchronized
方法的时候,如果有其他线程想同时执行synchronized
方法,那么它将会阻塞直至线程A所正在执行的synchronized
方法结束。同一时刻,只能有一个线程执行一个类中的一个synchronized
方法。
在实际使用中,可以使用synchronized
来锁一部分代码,而不是整个方法:
synchronized(this){ //...}
而且这样还可以根据需要来锁定不同的对象,而不是整个类:
private final Object cinemaA = new Object();private final Object cinemaB = new Object();/** 影院A销售票,锁定cinemaA对象即可 **/public void cinemaASellTickets(){ synchronized(cinemaA) { //... }}/** 影院B销售票,锁定cinemaB对象即可 **/public void clinemaBSellTickets(){ synchronized(cinemaB){ //... }}
在synchronized代码块中使用条件
0 0
- JAVA线程-JAVA同步
- Java线程:线程的同步-同步方法
- Java线程:线程的同步-同步块
- Java线程:线程的同步-同步方法
- Java线程:线程的同步-同步块
- Java线程:线程的同步-同步方法
- Java线程:线程的同步-同步方法
- Java线程:线程的同步-同步块
- Java线程:线程的同步-同步方法
- Java线程:线程的同步-同步块
- Java线程:线程的同步-同步方法
- Java线程:线程的同步-同步块
- Java线程:线程的同步-同步方法
- Java线程:线程的同步-同步块
- Java线程:线程的同步-同步方法
- Java线程:线程的同步-同步块
- Java线程:线程的同步-同步方法
- Java线程:线程的同步-同步方法
- Openwrt 学习记录:openWRT添加内核模块(五)
- 小贝_mysql select5种子句介绍
- leetcode Add and Search Word - Data structure design回溯算法+Trie字典树
- genymotion升级风波-engine not found 及virtual box 的无法打开新任务
- 高级进阶自己需要掌握的东西
- Java线程同步
- JavaScript在网页中的位置
- SQLite基本语句
- (oracle)invalid username/password:logon denied
- shell脚本中的命令替换
- iOS开发学习笔记(二)—— 让图片“动”起来!
- Notepad++选中行操作 快捷键 使用技巧
- GoF23种设计模式
- ora-01843错误