Java之线程安全的几种方式
生活随笔
收集整理的這篇文章主要介紹了
Java之线程安全的几种方式
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 一、使用synchronized重寫run方法
- 二、使用synchronized修飾方法(同步方法)
- 三、使用同步鎖Lock
一、使用synchronized重寫run方法
在多線程中,若不使用synchronzied保證線程安全,則可能會應為線程的切換帶來一些數據異常
如銀行取錢
運行結果如下:
解決代碼(使用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之线程安全的几种方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于HTML两侧留白的解决以及解决过程
- 下一篇: Dbeaver连接MySQL