Java并发编程实战(使用synchronized实现同步方法)
本文介绍java最基本的同步方式,即使用synchronized关键字来控制一个方法的并发访问,如果一个对象已用synchronized关键字声明,那么只有一个执行线程允许去访问它,其它试图访问这个对象的线程将被挂起,直到第一个线程访问完毕。
下面通过一个小例子来学习这个概念,公司向银行存钱,取钱场景。
1:创建Account的账号类,它是银行账户的模型,只有一个双精度浮点型属性,balance.
2:实现balance的get set 方法。
3:实现AddAmount()方法,将传入的数量加到余额balance中,并且在同一时间只允许一个线程去改变这个值,使用synchronized关键字。
4:实现SubtractAmount()方法,将传入的数量从余额balance中扣除,并且在同一时间只允许一个线程去改变这个值。
具体代码:
public class Account {
/**
* Balance of the bank account
*/
private double balance;
/**
* Returns the balance of the account
* @return the balance of the account
*/
public double getBalance() {
return balance;
}
/**
* Establish the balance of the account
* @param balance the new balance of the account
*/
public void setBalance(double balance) {
this.balance = balance;
}
/**
* Add an import to the balance of the account
* @param amount import to add to the balance
*/
public synchronized void addAmount(double amount) {
double tmp=balance;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
tmp+=amount;
balance=tmp;
}
/**
* Subtract an import to the balance of the account
* @param amount import to subtract to the balance
*/
public synchronized void subtractAmount(double amount) {
double tmp=balance;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
tmp-=amount;
balance=tmp;
}
}
5:实现一个ATM模拟类Bank,它使用subtractAmount()方法对账户的余额进行扣除,实现Runabl接口。
具体代码:
public class Bank implements Runnable {
/**
* The account affected by the operations
*/
private Account account;
/**
* Constructor of the class. Initializes the account
* @param account The account affected by the operations
*/
public Bank(Account account) {
this.account=account;
}
/**
* Core method of the Runnable
*/
public void run() {
for (int i=0; i<100; i++){
account.subtractAmount(1000);
}
}
}
6:实现公司模拟类,调用addAmount()方法进行存钱,实现Runabl接口。
具体代码:
public class Company implements Runnable {
/**
* The account affected by the operations
*/
private Account account;
/**
* Constructor of the class. Initializes the account
* @param account the account affected by the operations
*/
public Company(Account account) {
this.account=account;
}
/**
* Core method of the Runnable
*/
public void run() {
for (int i=0; i<100; i++){
account.addAmount(1000);
}
}
7:在主方法中调用测试:通过线程的join方法,在存期那,取钱线程模拟完毕后打印出结构。
public class Main {
/**
* Main method of the example
* @param args
*/
public static void main(String[] args) {
// Creates a new account ...
Account account=new Account();
// an initialize its balance to 1000
account.setBalance(1000);
// Creates a new Company and a Thread to run its task
Company company=new Company(account);
Thread companyThread=new Thread(company);
// Creates a new Bank and a Thread to run its task
Bank bank=new Bank(account);
Thread bankThread=new Thread(bank);
// Prints the initial balance
System.out.printf("Account : Initial Balance: %f\n",account.getBalance());
// Starts the Threads
companyThread.start();
bankThread.start();
try {
// Wait for the finalization of the Threads
companyThread.join();
bankThread.join();
// Print the final balance
System.out.printf("Account : Final Balance: %f\n",account.getBalance());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
结果,相同时间内,存与取执行后应该是相等的。如果我们在方法中不去使用synchronized关键字,那么得出的结果就不对了。
Account : Initial Balance: 1000.000000
Account : Final Balance: 1000.000000
Java并发编程实战(使用synchronized实现同步方法)的更多相关文章
- 【Java并发编程实战】-----synchronized
在我们的实际应用当中可能经常会遇到这样一个场景:多个线程读或者.写相同的数据,访问相同的文件等等.对于这种情况如果我们不加以控制,是非常容易导致错误的.在java中,为了解决这个问题,引入临界区概念. ...
- 【Java并发编程实战】—–synchronized
在我们的实际应用其中可能常常会遇到这样一个场景:多个线程读或者.写相同的数据,訪问相同的文件等等.对于这样的情况假设我们不加以控制,是非常easy导致错误的. 在java中,为了解决问题,引入临界区概 ...
- Java并发编程实战——读后感
未完待续. 阅读帮助 本文运用<如何阅读一本书>的学习方法进行学习. P15 表示对于书的第15页. Java并发编程实战简称为并发书或者该书之类的. 熟能生巧,不断地去理解,就像欣赏一部 ...
- 【Java并发编程实战】----- AQS(三):阻塞、唤醒:LockSupport
在上篇博客([Java并发编程实战]----- AQS(二):获取锁.释放锁)中提到,当一个线程加入到CLH队列中时,如果不是头节点是需要判断该节点是否需要挂起:在释放锁后,需要唤醒该线程的继任节点 ...
- 【Java并发编程实战】-----“J.U.C”:ReentrantLock之一简介
注:由于要介绍ReentrantLock的东西太多了,免得各位客官看累,所以分三篇博客来阐述.本篇博客介绍ReentrantLock基本内容,后两篇博客从源码级别分别阐述ReentrantLock的l ...
- 【java并发编程实战】-----线程基本概念
学习Java并发已经有一个多月了,感觉有些东西学习一会儿了就会忘记,做了一些笔记但是不系统,对于Java并发这么大的"系统",需要自己好好总结.整理才能征服它.希望同仁们一起来学习 ...
- java并发编程实战学习(3)--基础构建模块
转自:java并发编程实战 5.3阻塞队列和生产者-消费者模式 BlockingQueue阻塞队列提供可阻塞的put和take方法,以及支持定时的offer和poll方法.如果队列已经满了,那么put ...
- 《java并发编程实战》笔记
<java并发编程实战>这本书配合并发编程网中的并发系列文章一起看,效果会好很多. 并发系列的文章链接为: Java并发性和多线程介绍目录 建议: <java并发编程实战>第 ...
- 《Java并发编程实战》文摘
更新时间:2017-06-03 <Java并发编程实战>文摘,有兴趣的朋友可以买本纸质书仔细研究下. 一 线程安全性 1.1 什么是线程安全性 当多个线程访问某个类时,不管运行时环境采用何 ...
- Java并发编程实战.笔记十一(非阻塞同步机制)
关于非阻塞算法CAS. 比较并交换CAS:CAS包含了3个操作数---需要读写的内存位置V,进行比较的值A和拟写入的新值B.当且仅当V的值等于A时,CAS才会通过原子的方式用新值B来更新V的值,否则不 ...
随机推荐
- C# MVC模式 404 500页面设置方法
<customErrors mode="On" defaultRedirect="Controllers/Action"> <error st ...
- JAVA同步容器和并发容器
同步容器类 同步容器类的创建 在早期的JDK中,有两种现成的实现,Vector和Hashtable,可以直接new对象获取: 在JDK1.2中,引入了同步封装类,可以由Collections.sync ...
- informatica 学习日记整理
1. INFORMATICA CLIENT的使用 1.1 Repository Manager 的使用 1.1.1 创建Repository. 前提: a.在ODBC数据源管理器中新建一个数据源连接至 ...
- ORACLE 查看有多个执行计划的SQL语句
在SQL优化过程,有时候需要查看哪些SQL具有多个执行计划(Multiple Executions Plans for the same SQL statement),因为同一个SQL有多个执行计划一 ...
- 双十一来了,别让你的mongodb宕机了
好久没过来吹牛了,前段时间一直赶项目,没有时间来更新博客,项目也终于赶完了,接下来就要面临双十一这场惊心动魄的处女秀考验, 我们项目中会有一个wcf集群,而集群地址则放在mongodb中,所以mong ...
- A cost-effective recommender system for taxi drivers
一个针对出租车司机有效花费的推荐系统 摘要 GPS技术和新形式的城市地理学改变了手机服务的形式.比如说,丰富的出租车GPS轨迹使得出做租车领域有新方法.事实上,最近很多工作是在使用出租车GPS轨迹数据 ...
- x01.os.13: 文件系统
停了两天电,忽然得空闲.找来破吉他,已然不成弦. 丁丁当当敲,敲到电来到.为把时间捡,熬夜三四点. 从我的置顶随笔 x01.Lab.Download 中下载 x01.os.12.t ...
- parted在2T以上硬盘上分区操作
parted分区生产环境如何使用? 1)pertend一般用于当硬盘(raid后)大于2t的时候分区操作,2t以下还是用fdisk分区 2)使用parted一般操作系统都已经安装好了 3)大于2t的因 ...
- Linux设置环境变量小结:设置永久变量&临时变量 全局变量&局部变量
1.总结背景 在linux系统下,如果你下载并安装了应用程序,很有可能在键入它的名称时出现“command not found”的提示内容.如果每次都到安装目标文件夹内,找到可执行文件来进行操作就太繁 ...
- python json
#-*-coding:utf-8-*- '''编码格式记得统一,不然容易出现中文乱码,推荐用utf-8''' import json ##################json单对象######## ...