天天看點

java 線程重入鎖:ReentrantLock 簡單案例

在這就簡單說下鎖重要性吧,鎖一般應用在安全方面。如項目中與錢相關的操作,單機情況下是基本沒安全方面的問題。像網站這種,情況一:線程不安全,當多個請求同時到達,他們可能同時執行,我們的普通限制可能會失效,取款金額就可能出現負數(這一般是不允許出現的情況)。情況一:線程安全,我這指的是加鎖,當多個請求同時到達,這樣就能達到一條一條請求執行的效果。

案例(有鎖的)

包:com.gx.mi_dome

三個類:     Jfdh_thread_lock( 鎖的實作) 、Jfdh_thread(線程同步鎖 繼承Thread線程 ) 、 zhixing(主方法函數)

zhixing.java代碼

package com.gx.mi_dome;
import com.gx.mi_dome.Jfdh_thread;
import com.gx.mi_dome.Jfdh_thread_lock;

public class zhixing {
	public static void main(String[] args) {
		Jfdh_thread_lock zhanghuone=new Jfdh_thread_lock(1000);//定義     使用者擁有1000積分
		//第二種:循環
		int BB=1;
		int A_CS=13;
	
		for(int a=0;a< BB;a++){
			BB++;
			if(zhanghuone.getDhjf() < A_CS){//目前剩餘積分 小于 目前所兌換積分
				System.out.println("兌換物品積分大于剩餘積分");
				break;//結束循環    小智
			}
			
			Jfdh_thread takeMoney4=new Jfdh_thread(zhanghuone, A_CS);//建立線程對象  執行兌換積分方法
			A_CS=A_CS+3;//每次兌換積分加3
//			Jfdh_thread takeMoney2=new Jfdh_thread(zhanghuone, B_CS);//takeMoney2.start();
			takeMoney4.start();//start 開始
				//等待線程完成 	// 線程休眠1000ms(一秒)
				try {Thread.sleep(500);} catch (InterruptedException e) {//補捉     中斷故障異常
					System.out.println("中斷故障異常");
				}

		}		
		System.out.println("目前剩餘積分:"+zhanghuone.getDhjf());
	}
	
}
           

Jfdh_thread_lock.java代碼

package com.gx.mi_dome;
import java.util.concurrent.locks.ReentrantLock;
/**
 * 
 * 鎖的實作(ReentrantLock 重入鎖)
 * 
 * @author 星月
 *
 */
public class Jfdh_thread_lock {
	
	/*
	 * 重入鎖(ReentrantLock)是一種遞歸無阻塞的同步機制。以前一直認為它是synchronized的簡單替代,
	 * 而且實作機制也相差太遠。不過最近實踐過程中發現它們之間還是有着天壤之别。
	 * 它提供了lock()方法:如果該鎖定沒有被另一個線程保持,則擷取該鎖定并立即傳回,将鎖定的保持計數設定為 1。
	 * 如果目前線程已經保持該鎖定,則将保持計數加 1,并且該方法立即傳回。
	 * 如果該鎖定被另一個線程保持,則出于線程排程的目的,禁用目前線程,并且在獲得鎖定之前,
	 * 該線程将一直處于休眠狀态,此時鎖定保持計數被設定為 1
	 */
     
//	ReentrantLock擷取鎖定與三種方式:
//	a) lock(), 如果擷取了鎖立即傳回,如果别的線程持有鎖,目前線程則一直處于休眠狀态,直到擷取鎖
//	b) tryLock(), 如果擷取了鎖立即傳回true,如果别的線程正持有鎖,立即傳回false;
//	c) tryLock(long timeout,TimeUnit unit), 如果擷取了鎖定立即傳回true,如果别的線程正持有鎖,會等待參數給定的時間,在等待的過程中,如果擷取了鎖定,就傳回true,如果等待逾時,傳回false;
//	d) lockInterruptibly:如果擷取了鎖定立即傳回,如果沒有擷取鎖定,目前線程處于休眠狀态,直到或者鎖定,或者目前線程被别的線程中斷
	
//  Thread.setPriority(10); 就算設定線程優先等級 (最大:10  ,最小:1)  也不一定先執行  這涉及cpu工作原理	
	private final ReentrantLock lock=new ReentrantLock();//建立鎖對象
	    
	/**
	 * 積分
	 */
	private Integer dhjf;
	
	public Integer getDhjf() {
		return dhjf;
	}

	public void setDhjf(Integer dhjf) {
		this.dhjf = dhjf;
	}

   //定義使用者積分
	public Jfdh_thread_lock(Integer dhjf) {
		this.dhjf = dhjf;
	}//帶參構造方法
	
	//方法函數    主要鎖的代碼塊
	public  void jfdh_Method(Integer dhjf_CS) {
	
		lock.lock();// 加鎖
		if (dhjf_CS <= this.dhjf) {
			// 模拟取積分成功
			System.out.println("兌換積分" + dhjf_CS + "分");
			// 線程暫停 10ms 模拟網絡傳輸
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			//  修改目前擁有積分
			this.dhjf = this.dhjf - dhjf_CS;
			System.out.println("剩餘積分為:" + this.dhjf);
		} else {
			System.out.println("積分兌換失敗");
		}
		lock.unlock();//解鎖	
	}

}
           

Jfdh_thread.java代碼

package com.gx.mi_dome;
import com.gx.mi_dome.Jfdh_thread_lock;
/**
 * 
 * 積分兌換線程同步鎖 繼承Thread線程
 * 
 * @author 星月
 *
 */
public class Jfdh_thread extends Thread{
	
	/**
	 * 積分線程鎖對象
	 */
	private Jfdh_thread_lock jfdh_thread_lock;
	
	/**
	 * 積分
	 */
	private Integer dhjf;
	
	//AccountLock  同步鎖
	public Jfdh_thread(Jfdh_thread_lock jfdh_thread_lock_CS,Integer dhjf_CS){
		this.jfdh_thread_lock=jfdh_thread_lock_CS;
		this.dhjf=dhjf_CS;
	}
	
	/**
	 * 模拟積分兌換方法
	 */
	@Override
	public void run() {
		jfdh_thread_lock.jfdh_Method(dhjf);
	}
	
}
           

自己寫的一個案例,新手勿噴。