1. 程式人生 > >java多執行緒操作例子-(以銀行存錢取錢為例)

java多執行緒操作例子-(以銀行存錢取錢為例)

     以前一直沒有養成一個梳理知識的習慣,今天覆習到多執行緒的知識的,想到的經典的存錢取錢多執行緒同步機制,今天在這裡梳理下,錯的地方請各位大佬指正

1:多執行緒同步的方法

1:使用synchronized關鍵字修飾方法和程式碼塊(這就是兩種了)

2:使用特殊變數volatitle關鍵字修飾

3:JAVA5.0引入了重入鎖機制

1: 先看不引入鎖我們存錢取錢會發生什麼

    1.1 :新建一個銀行類Bank
package testThread;

import org.omg.CORBA.PUBLIC_MEMBER;
import org.w3c.dom.css.Counter;
/**
 * 一本正經的假裝銀行
 *
 */
public class Bank {
	//賬戶餘額
	private int sum=0;
	
	/**
	 * 存錢
	 * @param money
	 */
	public synchronized void addMoney(int money) {
		sum+=money;
		System.out.println(System.currentTimeMillis()+"存進"+money);
	}
	
	/**
	 * 取錢
	 */
	public void subMoney(int money)
	{
		if(sum-money<0)
		{
			System.out.println("餘額不足");
			return;
		}else {
			sum-=money;
			System.out.println(System.currentTimeMillis()+"取出"+money);
		}
		
	}
	
	/**
	 * 查詢餘額
	 */
	public void lookMoney()
	{
	System.out.println("賬戶餘額"+sum);	
	}

}

2:建立顧客完成存錢取錢的操作

package testThread;
/**
 * 主方法完成.假裝兩個存錢和取錢的的(大佬有錢,一直存取)
 */
public class TestMain {
	 public static void main(String args[]){  
	        final Bank bank=new Bank();  
	        Thread tadd=new Thread(new Runnable() {  
	            @Override  
	            public void run() {  
	                // TODO Auto-generated method stub  
	                while(true){  
	                    try {  
	                        Thread.sleep(1000);  
	                    } catch (InterruptedException e) {  
	                        // TODO Auto-generated catch block  
	                        e.printStackTrace();  
	                    }  
	                    bank.addMoney(100);  
	                    bank.lookMoney();  
	                }  
	            }  
	        });  

	        Thread tsub = new Thread(new Runnable() {  

	            @Override  
	            public void run() {  
	                // TODO Auto-generated method stub  
	                while(true){  
	                    bank.subMoney(100);  
	                    bank.lookMoney();  
	                    try {  
	                        Thread.sleep(1000);  
	                    } catch (InterruptedException e) {  
	                        // TODO Auto-generated catch block  
	                        e.printStackTrace();  
	                    }     
	                }  
	            }  
	        });  
	        tsub.start();  
	        tadd.start();  
	    }  
}
1.3:截圖

結果分析:我電腦CPU處理的太快了,一直沒看到真正想要的結果真實的結果類似這個

餘額不足  
賬戶餘額:0  

餘額不足  
賬戶餘額:100(有一百你不讓我取,這個貨)
1441792010959存進:100  
賬戶餘額:100
為什麼出現這樣的結果呢,這個就是多執行緒同時操作同一個資源,沒有用同步機制,發生了小問題

2:引入synchronized關鍵字bank類

package testThread;

import org.omg.CORBA.PUBLIC_MEMBER;
import org.w3c.dom.css.Counter;
/**
 * 假裝銀行
 *
 */
public class Bank {
	//賬戶餘額
	private int sum=0;
	
	/**
	 * 存錢
	 * @param money
	 */
	public 
synchronized void addMoney(int money) { sum+=money; System.out.println(System.currentTimeMillis()+"存進"+money); } /** * 取錢 */ public synchronized void subMoney(int money) { if(sum-money<0) { System.out.println("餘額不足"); return; }else { sum-=money; System.out.println(System.currentTimeMillis()+"取出"+money); } } /** * 查詢餘額 */ public void lookMoney() { System.out.println("賬戶餘額"+sum); } }


在看看執行結果


咳咳,其實是上面的圖...........懂就好(synchronized 當然也可以修飾靜態的方法,不過呼叫它的時候會封鎖整個類);

3:synchronized修飾的程式碼塊

package testThread;

import org.omg.CORBA.PUBLIC_MEMBER;
import org.w3c.dom.css.Counter;
/**
 * 假裝銀行
 *
 */
public class Bank {
	//賬戶餘額
	private int sum=0;
/**
	 * 存錢
	 * @param money
	 */
	public  void addMoney(int money) {
		synchronized(this)
		{
			sum+=money;
			System.out.println(System.currentTimeMillis()+"存進"+money);
		}
	}

/**
	 * 取錢
	 */
	public void subMoney(int money)
	{
		 synchronized(this)
		 {
		     if(sum-money<0)
			{
			System.out.println("餘額不足");
			return;
			}else {
				sum-=money;
				System.out.println(System.currentTimeMillis()+"取出"+money);
			} 
		 }
	
	}
	/**
	 * 查詢餘額
	 */
	public void lookMoney()
	{
	System.out.println("賬戶餘額"+sum);	
	}

}

結果和上面的一樣

4:使用volatitle關鍵字

package testThread;
/**
 * 假裝
 *
 */
public class Bank {
	//賬戶餘額
	private volatile int sum=0;
	
	/**
	 * 存錢
	 * @param money
	 */
	public void addMoney(int money) {
		sum+=money;
		System.out.println(System.currentTimeMillis()+"存進"+money);
	}
	
	/**
	 * 取錢
	 */
	public void subMoney(int money)
	{
		if(sum-money<0)
		{
			System.out.println("餘額不足");
			return;
		}else {
			sum-=money;
			System.out.println(System.currentTimeMillis()+"取出"+money);
		}
		
	}
	
	/**
	 * 查詢餘額
	 */
	public void lookMoney()
	{
	System.out.println("賬戶餘額"+sum);	
	}

}

結果分析

餘額不足  
賬戶餘額:0餘額不足  
賬戶餘額:100

1441792010959存進:100  
賬戶餘額:100  

1441792011960取出:100  
賬戶餘額:0  

1441792011961存進:100  
賬戶餘額:100

結果又tmd不讓取了,,這個是為啥呢

因為volatitle不能保證原子操作導致,每次執行緒要訪問volatitle變數都是從記憶體中去讀的,而是不是從快取中讀的,這就保證每個執行緒訪問的變數是一樣的,這就保證了同步

5:使用重入鎖實現執行緒同步

啥也不說,老規矩,上程式碼

package testThread;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Bank{
	//賬戶餘額
	private  int sum=0;
	
	//1.1: 我們需要先申明這個鎖
	private Lock lock=new ReentrantLock();
	/**
	 * 存錢
	 * @param money
	 */
	public void addMoney(int money) {
		//1.2上鎖
		lock.lock();
		try {
			sum+=money;
			System.out.println(System.currentTimeMillis()+"存進"+money);
		} catch (Exception e) {
			// TODO: handle exception
		}finally{
			//1.3解鎖
			lock.unlock();
		}
		
	}
	
	/**
	 * 取錢
	 */
	public void subMoney(int money)
	{
		//1.1上鎖
		lock.lock();
		try {
			if(sum-money<0)
			{
				System.out.println("餘額不足");
				return;
			}else {
				sum-=money;
				System.out.println(System.currentTimeMillis()+"取出"+money);
			}
		} finally{
			//接鎖
			lock.unlock();
		}
		
		
	}
	
	/**
	 * 查詢餘額
	 */
	public void lookMoney()
	{
	System.out.println("賬戶餘額"+sum);	
	}

}

結果分析:

和上上圖結果一樣,不貼了,老鐵....

我們一般同步用synchronized,如果你想要用高階一點的,用lock,但別忘了釋放一下,不理會發生死鎖的哦,同學

相關推薦

java執行操作例子-(銀行存錢)

     以前一直沒有養成一個梳理知識的習慣,今天覆習到多執行緒的知識的,想到的經典的存錢取錢多執行緒同步機制,今天在這裡梳理下,錯的地方請各位大佬指正1:多執行緒同步的方法1:使用synchronized關鍵字修飾方法和程式碼塊(這就是兩種了)2:使用特殊變數volatit

java執行經典問題二--銀行存錢問題

例項:兩個人向同一個賬戶裡面存錢 public class Demo { public static void main(String[] args) { //1.建立任務

java執行操作兩個資料庫.

package com.dinglin; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; i

java 執行操作 安全操作 synchronized

java 多執行緒操作 安全操作 synchronized 記錄程式碼如下 Thread myThread = new Thread(new Runnable() { @Override public void run() { // synchro

Java執行操作區域性變數與全域性變數

在這篇文章裡,我們首先闡述什麼是同步,不同步有什麼問題,然後討論可以採取哪些措施控制同步,接下來我們會仿照回顧網路通訊時那樣,構建一個伺服器端的“執行緒池”,JDK為我們提供了一個很大的concurrent工具包,最後我們會對裡面的內容進行探索。   為什麼要執

執行經典案例:模仿儲戶

銀行取錢肯定不能透支這個是眾所周知的,實現此功能就需要藉助多執行緒的知識! 先來看一下采取同步措施前產生的結果: 好的,我們先來定義一個賬戶類: /** * 賬戶類,含卡號,還有餘額 通過同步方法防止出現餘額為負的情況 * * @author Mr.Gao *

Java執行同步---銀行存取的過程的簡單程式碼例項

首先存錢取錢的這個操作,應該是執行緒操作的,可以有很多的顧客,這意思就是得有多個執行緒,多個執行緒之間共同操作一個銀行,銀行的金額就需要同步。才能保證執行緒安全。 所以,下面就把這個程式碼的例項放 這,有不對的地方,還請指出來哈。因為有個老鐵問這個多執行緒的程式碼。 首先是

java執行入門案例(1)之簡單銀行取款問題及其優化

      之前學java的時候,學校老師由於課時問題,沒有教我們多執行緒,最近學校外聘的企業教師給我們做實訓要用到多執行緒,因此才初步瞭解多執行緒,以下這個案例只是介紹java程式碼優化,程式碼中有涉及多執行緒,但今天不對其講解,只簡單講解程式碼優化的問題,希望對初學

Java執行開發——一個簡單的數字加減小例子

範例: 兩個執行緒實現加法,兩個執行緒實現減法 class Resource { private int num = 0; private boolean flag = true; //flag = true 表示可以進行加法操作,不能進行減法操作 //flag = fa

Java執行併發總結】Thread類的常用方法(join、yield等)---執行的基礎操作

 啟動(start)   最基本的操作,呼叫Runnable中的run方法,無返回值。 new Thread(new Test()).start(); 休眠(sleep)  使當前執行緒休眠一段時間,預設為毫秒級,最高可以精確到納秒,呼叫的方法為slee

Java執行11:執行同步操作

什麼情況下需要同步 1、當多執行緒併發,有多段程式碼同時執行時,有時希望某一段程式碼執行的過程中CPU不要切換到其他執行緒工作。這時就需要執行緒同步。 2、如果兩段程式碼是同步的,那麼同一段時間只能執行

Java執行----執行的同步,鎖和死鎖,問題以及解決方法(例子說明)

一、執行緒併發同步概念 執行緒同步其核心就在於一個“同”。所謂“同”就是協同、協助、配合,“同步”就是協同步調昨,也就是按照預定的先後順序進行執行,即“你先,我等, 你做完,我再做”。 執行緒同步,就是當執行緒發出一個功能呼叫時,在沒有得到結果之前,該呼叫就不會返回,其他

【Dr.Chen的系列問題】Java執行的實現操作

一、什麼是多執行緒? 多執行緒(英語:multithreading),是指從軟體或者硬體上實現多個執行緒併發執行的技術。具有多執行緒能力的計算機因有硬體支援而能夠在同一時間執行多於一個執行緒,進而提升整體處理效能。具有這種能力的系統包括對稱多處理機、多核心處理器以及晶片級多

Java執行16:使用ReentrantLock類實現同步操作

在Java多執行緒中,可以使用synchronized關鍵字來實現執行緒之間同步互斥,但在JDK1.5中新增加了ReentrantLock類也能達到同步的效果,並且在擴充套件功能上也更加強大。 pack

java執行案例1之簡單銀行取款問題及其優化

      之前學java的時候,學校老師由於課時問題,沒有教我們多執行緒,最近學校外聘的企業教師給我們做實訓要用到多執行緒,因此才初步瞭解多執行緒,以下這個案例只是介紹java程式碼優化,程式碼中有涉及多執行緒,但今天不對其講解,只簡單講解程式碼優化的問題,希望對初學者有幫

java 執行 同步 觀察者 併發集合的一個例子

//第一版 package com.hra.riskprice; import com.hra.riskprice.SysEnum.Factor_Type; import org.springframework.boot.SpringApplication; import org.springfram

Java Thread 執行 操作執行

建立、啟動執行緒 執行緒的實現方式 執行緒的生命週期 執行緒的狀態 控制執行緒 5、執行緒的建立和啟動 A、繼承Thread類或實現Runnable介面,重寫或實現run方法,run方法代表執行緒要完成的任務 B、建立Thread子類或是Ru

Java執行程式設計-(14)-無鎖CAS操作以及Java中Atomic併發包的“18羅漢”

原文出自 : https://blog.csdn.net/xlgen157387/article/details/78364246 上一篇: Java多執行緒程式設計-(13)- 關於鎖優化的幾點建議 一、背景 通過上面的學習,我們應該很清楚的

java 執行基礎之銀行號排隊系統

練習:銀行取號排隊 規則:銀行有四個視窗 1個vip視窗,只能接待vip顧客,另外三個視窗優先接待vip客戶 這裡對於執行緒的一些基礎介紹我就不累贅了 主要講講銀行排隊執行緒要注意哪些點? 1.肯定要寫一個客戶實體類,主要存放客戶的票號和客戶的種類(普通或VIP) 2

模擬銀行 (執行操作的好處)

(1)銀行類 package test4; /**  * 銀行賬戶  * @author user  *  */ public class Bank {private static double ba