java蛇皮多線程(終章)

  多線程同步


舉個銀行取錢的例子來說

public class ThreadTest13 {

	public static void main(String[] args) {
		Account account=new Account("叫我男神O(∩_∩)O",5000);
		Thread t1=new Thread(new Processor(account));
		Thread t2=new Thread(new Processor(account));
		t1.start();
		t2.start();
	}

}
//取款的線程
class Processor implements Runnable{
	//賬戶
	Account act;
	Processor(Account act){
		this.act=act;
	}
	
	public void run() {
		act.withdraw(1000);
		System.out.println(act.getActno()+"取款1000塊成功,餘額:"+act.getbalance());
		
	}
}
//賬戶
class Account{
	//屬性
	private String actno;
	private double balance;
	//構造方法
	public Account() {}
	public Account(String actno,double balance) {
		this.setActno(actno);
		this.setbalance(balance);
	
	}
	//set and get
	public String getActno() {
		return actno;
	}
	public void setActno(String actno) {
		this.actno=actno;
	}
	public double getbalance() {
		return balance;
		
	}
	public void setbalance(double balance) {
		this.balance=balance;
		
	}
	//對外提供一個取款的方法
	public synchronized void withdraw(double money) {
		synchronized (this) {
			//把要同步的代碼放到同步語句塊
			/*
			 * 原理t1 和t2
			 * t1線程執行到此處,遇到的synchroized這個關鍵字,就回去找this對象鎖
			 *如果找到了this對象鎖,則進入同步語句塊中執行程序,當同步語句塊中代碼執行結束,t1線程歸還this對象鎖。
			 *
			 * 在t1線程執行同步語句塊過程中,如果t2線程也過來執行以下程序,也會遇到synchronzed關鍵字,所以也去找this對象鎖,但是該對象鎖被t1線程持有,只能在此處等待this對象鎖的歸還
			 */
			double after=balance-money;
			//更新
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				
				e.printStackTrace();
			}
			this.setbalance(after);
			
		}
	}
	
}


關於synchronized(鎖)的小方面



t1與t2共享一個資源時(同一個進程的線程是共享其進程的*內存和資源*

共享的內存是*堆內存和方法內存*  棧內存不共享,每個線程有自己的棧空間(一個線程一個棧))

public class ThreadTest14 {

	public static void main(String[] args) throws InterruptedException {
		// TODO 自動生成的方法存根
		MyClass mc =new MyClass();
		F a=new F(mc);//t1與t2共享一個mc
		Thread t1=new Thread(a);
		t1.setName("t1");
		Thread t2=new Thread(a);
		t2.setName("t2");
		t1.start();
		//保證t1先執行
		Thread.sleep(1000);
		t2.start();
		
	}

}
class F implements Runnable{
	MyClass mc;
	F(MyClass mc){
		this.mc=mc;
	}
	public void run() {
		if (Thread.currentThread().getName().equals("t1"))
			mc.m1();
		if(Thread.currentThread().getName().equals("t2"))
			mc.m2();
	}
}
class MyClass{
	public synchronized void m1() {
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			
			e.printStackTrace();
		}
		System.out.println("m1...");
	}
//	public  void m2() {	  m2不需要等m1結束m2   沒有synchronized關鍵字
//		System.out.println("m2....");
//	}
	public synchronized void m2(){//m2方法會等m1結束 t1和t2共享一個mc ,並且m1和m2都有synchronized
	System.out.println("m2......");
}
}
第一次m2沒加synchronized關鍵字(沒和m1公用一個茅坑)



第二次m2加了synchronized關鍵字(和m1共同享用一個茅坑)


對象鎖(不止一個)


m2方法不會等m1方法結束  ,t1和t2不共享同一mc內存。


public class ThreadTest15 {

	public static void main(String[] args) throws Exception {
		
		MyClass01 mc1 = new MyClass01();
		MyClass01 mc2 = new MyClass01();
		
		B b1 = new B(mc1);
		B b2 = new B(mc2);
		//*t1與t2 不共享同一mc內存*
		Thread t1 = new Thread(b1);
		t1.setName("t1");
		Thread t2 = new Thread(b2);
		t2.setName("t2");
		
		t1.start();
		//保證t1先執行
		Thread.sleep(1000);
		t2.start();
	}

}

class B implements Runnable{
	
	MyClass01 mc;
	
	B(MyClass01 mc){
		this.mc = mc;
	}
	
	@Override
	public void run() {
		if (Thread.currentThread().getName().equals("t1")) {
			mc.m1();
		}
		if (Thread.currentThread().getName().equals("t2")) {
			mc.m2();
		}
	}
	
}


class MyClass01{
	
	public synchronized void m1(){
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("m1....");
	}
	
	//m2方法不會等m1方法結束  ,t1和t2不共享一個mc
	public synchronized void m2(){
		System.out.println("m2......");
	}
	
	
}



類鎖(只有一個,synchronized+靜態方法)

因爲有synchronized添加到靜態方法上面的,線程執行到此方法會找類鎖m2方法等m1方法結束之後才能執行,雖然t1與t2的mc對象不一樣,但是m2方法還是會等m1的

(就好像兩個人,分別去兩個不同的茅坑上廁所,但是隻有你手裏有一瓢水可以衝,他不確定他上的時候有沒有水衝,所以得等你上完,再拿水上)


/*
 * 類鎖  類只有一個  所以是類級別的,只有一個
 * */
public class ThreadTest16 {

	public static void main(String[] args) throws Exception {
		MyClass03 mc1 = new MyClass03();
		MyClass03 mc2 = new MyClass03();
		
		Thread t1 = new Thread(new D(mc1));
		Thread t2 = new Thread(new D(mc2));
		
		t1.setName("t1");
		t2.setName("t2");
		
		t1.start();
		Thread.sleep(1000);
		t2.start();

	}

}

class D implements Runnable{
	MyClass03 mc;
	
	D(MyClass03 mc){
		this.mc = mc;
	}
	
	public void run(){
		if ("t1".equals(Thread.currentThread().getName())) {
			mc.m1();//用的還是類鎖  和對象沒有關係
		}
		if("t2".equals(Thread.currentThread().getName())){
			mc.m2();
		}
	}
	
}

class MyClass03{
	
	//synchronized  添加到靜態方法上面的,線程執行到此方法會找類鎖
	public synchronized static void m1(){
		
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("m1......");
	}
	
	//m2方法等m1方法結束之後才能執行,因爲有synchronized
	//線程執行該代碼需要類鎖  但是類鎖只有一個
	public synchronized static void m2(){
		System.out.println("m2......");
	}
	
}





Thread.setDaemon(true);

 *守護線程
 
  等其他用戶線程全部結束後則守護線程退出
 
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章