文章目录

  • 一、使用synchronized重写run方法
  • 二、使用synchronized修饰方法(同步方法)
  • 三、使用同步锁Lock

一、使用synchronized重写run方法

在多线程中,若不使用synchronzied保证线程安全,则可能会应为线程的切换带来一些数据异常
如银行取钱

public class Thread_safe_acount {private String accountNo;private double balance;public Thread_safe_acount( ){}public Thread_safe_acount(String accountNo, double balance) {this.accountNo = accountNo;this.balance = balance;}public void setAccountNo(String accountNo) {this.accountNo = accountNo;}public void setBalance(double balance) {this.balance = balance;}public String getAccountNo() {return accountNo;}public double getBalance() {return balance;}// 重写hashCode@Overridepublic int hashCode() {return accountNo.hashCode();}@Overridepublic boolean equals(Object obj) {if(this == obj){return true;}if(obj!=null && obj.getClass()==Thread_safe_acount.class ){Thread_safe_acount target = (Thread_safe_acount) obj;return(target.getAccountNo().equals(accountNo));}return false;}}
public class Thread_safe_main extends Thread {private Thread_safe_acount account;private double need;public Thread_safe_main() {}public Thread_safe_main(String name, Thread_safe_acount account, double need) {super(name);this.account = account;this.need = need;}@Overridepublic void run() {if (account.getBalance() >= need) {try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}account.setBalance(account.getBalance() - need);System.out.println("客户" + getName() + "取钱成功,当前账户余额:" + (account.getBalance()));} else if (account.getBalance() < need) {System.out.println("当前余额不足!");}}public static void main(String[] args) {for (int i = 0; i < 20; i++) {Thread_safe_acount tsa1 = new Thread_safe_acount("001", 100);Thread_safe_main tsm1 = new Thread_safe_main("张三丰", tsa1, 100);Thread_safe_main tsm2 = new Thread_safe_main("张四丰", tsa1, 100);tsm1.start();tsm2.start();}}}

运行结果如下:

解决代码(使用synchronized重写run)

public class Thread_Truesafe_main extends Thread {private Thread_safe_acount account;private double need;public Thread_Truesafe_main() {}public Thread_Truesafe_main(String name, Thread_safe_acount account, double need) {super(name);this.account = account;this.need = need;}@Overridepublic void run() {synchronized (account) {if (account.getBalance() >= need) {try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}account.setBalance(account.getBalance() - need);System.out.println("客户" + getName() + "取钱成功,当前账户余额:" + (account.getBalance()));} else if (account.getBalance() < need) {System.out.println("当前余额不足!");}}}public static void main(String[] args) {// for (int i = 0; i < 20; i++) {Thread_safe_acount tsa1 = new Thread_safe_acount("001", 100);Thread_Truesafe_main tsm1 = new Thread_Truesafe_main("张三丰", tsa1, 100);Thread_Truesafe_main tsm2 = new Thread_Truesafe_main("张四丰", tsa1, 100);tsm1.start();tsm2.start();// }}}

运行结果:

二、使用synchronized修饰方法(同步方法)

public class Thread_safe_acount_Synchronized {private String accountNo;private double balance;public Thread_safe_acount_Synchronized( ){}public Thread_safe_acount_Synchronized(String accountNo, double balance) {this.accountNo = accountNo;this.balance = balance;}public void setAccountNo(String accountNo) {this.accountNo = accountNo;}public String getAccountNo() {return accountNo;}public double getBalance() {return balance;}public synchronized void draw(double need) {if (balance >= need) {try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}balance=balance - need;System.out.println("客户" + Thread.currentThread().getName() + "取钱成功,当前账户余额:" + balance);} else if (balance < need) {System.out.println("当前余额不足!");}}// 重写hashCode@Overridepublic int hashCode() {return accountNo.hashCode();}@Overridepublic boolean equals(Object obj) {if(this == obj){return true;}if(obj!=null && obj.getClass()==Thread_safe_acount_Synchronized.class ){Thread_safe_acount_Synchronized target = (Thread_safe_acount_Synchronized) obj;return(target.getAccountNo().equals(accountNo));}return false;}}

测试类:

public class Thread_safe_main_synchronized extends Thread {private Thread_safe_acount_Synchronized account;private double need;public Thread_safe_main_synchronized() {}public Thread_safe_main_synchronized(String name, Thread_safe_acount_Synchronized account, double need) {super(name);this.account = account;this.need = need;}@Overridepublic void run() {account.draw(need);}public static void main(String[] args) {// for (int i = 0; i < 20; i++) {Thread_safe_acount_Synchronized tsa1 = new Thread_safe_acount_Synchronized("001", 100);Thread_safe_main_synchronized tsm1 = new Thread_safe_main_synchronized("张三丰", tsa1, 100);Thread_safe_main_synchronized tsm2 = new Thread_safe_main_synchronized("张四丰", tsa1, 100);tsm1.start();tsm2.start();// }}}

执行结果:

优点:

  • 更符合面向对象规划
  • 领域驱动设计模式(DDD,Domain Driven Design)认为每个类都应该是完备的领域对象,比如account类除了具备基本属性外,还应有转账、取钱等相应的与账户相关的方法。从而保证对象的完整性和一致性。

三、使用同步锁Lock

import java.util.concurrent.locks.ReentrantLock;public class Thread_safe_acount_Lock {private final ReentrantLock lock =new ReentrantLock();private String accountNo;private double balance;public Thread_safe_acount_Lock( ){}public Thread_safe_acount_Lock(String accountNo, double balance) {this.accountNo = accountNo;this.balance = balance;}public void setAccountNo(String accountNo) {this.accountNo = accountNo;}public String getAccountNo() {return accountNo;}public double getBalance() {return balance;}public void draw(double need){lock.lock();try{if (balance >= need) {try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}balance=balance - need;System.out.println("客户" + Thread.currentThread().getName() + "取钱成功,当前账户余额:" + balance);} else if (balance < need) {System.out.println("当前余额不足!");}} finally {lock.unlock();}}// 重写hashCode@Overridepublic int hashCode() {return accountNo.hashCode();}@Overridepublic boolean equals(Object obj) {if(this == obj){return true;}if(obj!=null && obj.getClass()==Thread_safe_acount_Lock.class ){Thread_safe_acount_Lock target = (Thread_safe_acount_Lock) obj;return(target.getAccountNo().equals(accountNo));}return false;}}

测试代码:

public class Thread_safe_main_Lock extends Thread {private Thread_safe_acount_Lock account;private double need;public Thread_safe_main_Lock() {}public Thread_safe_main_Lock(String name, Thread_safe_acount_Lock tsa1, double need) {super(name);this.account = tsa1;this.need = need;}@Overridepublic void run() {account.draw(need);}public static void main(String[] args) {// for (int i = 0; i < 20; i++) {Thread_safe_acount_Lock tsa1 = new Thread_safe_acount_Lock("001", 100);Thread_safe_main_Lock tsm1 = new Thread_safe_main_Lock("张三丰", tsa1, 100);Thread_safe_main_Lock tsm2 = new Thread_safe_main_Lock("张四丰", tsa1, 100);tsm1.start();tsm2.start();// }}}

结果:

Java之线程安全的几种方式相关推荐

  1. java实现线程安全的三种方式

    前言 一个程序在运行起来的时候会转换成进程,通常含有多个线程.通常情况下,一个进程中的比较耗时的操作(如长循环.文件上传下载.网络资源获取等),往往会采用多线程来解决. 比如现实生活中,银行取钱问题. ...

  2. Java创建线程池的几种方式

    方式一:继承Thread类 新建一个类并该类声明为Thread的子类. 这个子类应该重写run类的方法.例如,计算大于规定值的素数的线程可以写成如下: class PrimeThread extend ...

  3. Java实现线程安全的几种方式

    文章目录 一.不可变 二.互斥同步 三.非阻塞同步 1. CAS 2. AtomicInteger 3. ABA 四.无同步方案 1. 栈封闭 2. 线程本地存储(Thread Local Stora ...

  4. java实现线程通信的几种方式

    前言 在多线程的世界里,线程与线程之间的交互无处不在,只不过在平时的开发过程中,大多数情况下,我们都在单线程的模式下进行编码,即使有,也直接借助框架自身的机制实现了,其实线程之间的通信在JDK中是一个 ...

  5. java创建线程常用的两种方式

    一.继承Thread类创建线程类 (1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代 表了线程要完成的任务.因此把run()方法称为执行体. (2)创建Thread子类的 ...

  6. Java线程同步的几种方式

    Java线程同步的几种方式 1.使用synchronized关键字  它的工作是对同步的代码加锁,使得每一次只能有一个线程进入同步块,从而保证线程间的安全性.  synchronized关键字的用法: ...

  7. java创建线程池几种方式_java知识总结-创建线程池的6种方式

    一.创建线程池的6种方式: Executors.newCachedThreadPool(); 创建一个可缓存线程池,应用中存在的线程数可以无限大 Executors.newFixedThreadPoo ...

  8. Java面试题:线程实现的两种方式及匿名内部类实现

    QUESTION:线程实现的两种方式及匿名内部类实现 ANSWER: 1.多线程两种实现方式 (1)继承Thread     * 定义类继承Thread     * 重写run方法     * 把新线 ...

  9. pyqt stop停止线程_面试阿里,字节跳动,腾讯90%都会被问到如何终止线程?有几种方式?你都知道吗?...

    在 Java 中有以下 3 种方法可以终止正在运行的线程: 使用退出标志,使线程正常退出,也就是当 run() 方法完成后线程终止: 使用 stop() 方法强行终止线程,但是不推荐使用这个方法,因为 ...

最新文章

  1. android frida 检测_frida测试方法整理
  2. UVA 10706 Number Sequence
  3. css背景图片添加url_CSS背景图片–如何向您的Div添加图片URL
  4. ios 内存管理的理解(五)ARC使用特点及注意事项
  5. java中HashSet对象内的元素的hashCode值不能变化
  6. halcon 差异模型 异物_基于HALCON的形状匹配算法的研究和心得总结
  7. matlab堆栈的思想,[转载]Matlab源代码:堆栈类Stack的实现
  8. 【BIRT】在页面上展示xxxx年xx月xx日
  9. android 9.0 c7Pro,三星c7pro和vivo x9哪个好?三星Galaxy c7 pro和vivo x9区别对比评测
  10. 在python中for i in range是什么意思-Python for i in range ()用法详解
  11. mac html字体设置,Mac Win 网页字体显示方案
  12. SAP中PR/PO创建技巧之缺省值个人设置
  13. JAVA基础(注释,关键字与标识符)
  14. 计算机c盘突然少了几个G,做系统时c盘显示0容量-关于Windows系统c盘突然没了十几个g...
  15. 20145212罗天晨 恶意代码分析
  16. Windows实用工具推荐
  17. altera fpga大小如何衡量_Xilinx和Altera FPGA的基本逻辑单元对比
  18. 手把手教你Java/JDK安装与环境搭建
  19. 【VBA】给单元格设置背景色
  20. AutoLayout详解

热门文章

  1. 把 textbox 遍历赋值为空
  2. Struts 2(一):初识Struts
  3. Windows.Web.Http.HttpClient.GetStringAsync 总是返回相同的结果
  4. 启动tomcat时,一直卡在Deploying web application directory这块的解决方案
  5. MVC,MVP与MVVM
  6. 环境变量设置及第三方模块安装
  7. MySql数据库查询表信息/列信息(列ID/列名/数据类型/长度/精度/是否可以为null/默认值/是否自增/是否是主键/列描述)...
  8. codevs1688 求逆序对(权值线段树)
  9. Android之路-------Activity的详解
  10. 常见的Java WEB服务器