java核心卷之多線程核心內容學習筆記(一)

——每天寥寥的幾筆,堅持下去,將會是一份沉甸甸的積累。


老實說,多線程這塊學起來真不是很輕鬆。接下來,本人整理了下自己學習多線程這塊的一些核心內容(如果細講,恐不是一篇兩篇文章所能囊括的)


1.線程的概念: 通俗的理解,進程是一個大的運行的程序,而線程就是該程序裏面的一些子程序(功能)

                          專業的說,線程是CPU使用的基本單元,由線程ID,程序計數器,寄存器集合和棧組成,它與屬於同一進程的其他線程共享代碼段,數據段和其他資源。

從上面介紹中,要理解的核心暫時就是:共享數據。因此多個線程搶一份資源,結果就出現了線程安全,因此,線程的相關處理就很重要了。


2.無腦的使用(會使用是最低級別的,懂原理可居中層,理解底層源碼實現的可居高層,自己可以按需修改源碼並實現之的則乃高人也)

兩種創建線程的方法,

其一:繼承Thread類創建一子類,然後覆寫run方法,並new出該子類的實例對象(構造函數的參數就是你要共享,或許就是一個遙控器對象),最後調用start方法。

其二:一個類實現runnable接口,實現run方法,然後用這個類的對象作爲參數new出相關Thread對象,該對象就是該類的一個線程,調用start函數啓動線程。


3.多線程的高性能(多個同時併發執行),但也存在缺點,就是共享數據

如何創建多線程共享一份數據,對應上面的兩種方法,實例代碼如下

public class Share {//作爲共享數據的對象類
	private int shareNum;
	Share(int num){
		this.shareNum = num;
	}
	public synchronized int getShareNum(){//由於該對象共享,必須添加synchronized關鍵字避免同時操作
		return this.shareNum;
	}
}

//方法一:繼承Thread類
public class Method01 extends Thread{
	private Share share;
	Method01(Share share){//構造函數傳入共享數據
		this.share = share;
	}
	public void run(){

	}
}
//方法二:實現runnable接口
public class Method02 implements Runnable{
	private Share share;
	Method02(Share share){//構造函數傳入共享數據
		this.share = share;
	}
	public void run(){

	}
}

public class Test{
	//方法一
	Share share = new Share(10);//建公共的共享數據對象,以下線程都已該對象爲參數
	new Method01(share);//線程1,操作share
	new Method01(share);//線程2,操作share
	new Method01(share);//線程3,操作share
	new Method01(share);//線程4,操作share
	//方法二
        Runnable method02 = new Method02(share);//以公共對象share作爲參數構造公共的runnable對象method02,然後以下線程都以這個共享的runnable對象爲參數
        new Thread(method02);//線程1,操作method02
        new Thread(method02);//線程2,操作method02
        new Thread(method02);//線程3,操作method02
        new Thread(method02);//線程4,操作method02

   總結:其實方法二就是把方法一中的runnable接口對象給抽取出來了。
}

4.synchronized的注意點。

說這個關鍵字之前,大家必須清楚一個事實:java中的每一個對象都有一個內部鎖。線程A要調用該對象的synchronized的方法時,必須獲得該對象的鎖,而一旦拿到鎖,其他線程就拿不到改鎖,也就不能調用該方法,也就實現了阻塞的功能。

明白上面的概念,其實使用上沒啥難度:

其一:是直接加到方法返回類型前,則默認擁有了this對象的內部鎖;

其二:是同步阻塞,即

<span style="font-size:14px;">synchronized(obj){}//則擁有obj對象的鎖,該對象是程序員自己建出來的“虛擬鎖”</span>

但是,

但是,

有一點要注意,對於第一種方法——直接加到方法返回類型前的,由於默認擁有了this對象的內部鎖,因此該線程佔據了該類所有帶synchronized關鍵字前綴的方法的使用。而想避免這種情況出現,就可以選擇使用多個上面提到的虛擬鎖,不同的方法用第二種方法控制不同的虛擬鎖。比如:

public class A{
	private Object obj1;
	private Object obj2;
	void B(){
		synchronized(obj1){
			//to-do-something
		}
	}
	void C(){
		synchronized(obj2){
			//to-do-something
		}
	}
	//這樣方法B和C就不耦合了
}



線程的知識遠不止這些。。。初級知識就不多寫了,中級知識——有關中斷,notify,notifyall,wait的下一篇文章再介紹吧。





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