多線程的理解(簡介)


進程正在進行中的程序。其實進程就是一個應用程序運行時的內存分配空間。

線程其實就是進程中一個程序執行控制單元,一條執行路徑。進程負責的是應用程序的空間的標示。線程負責的是應用程序的執行順序。

總而言之,一個進程至少有一個線程在運行,當一個進程中出現多個線程時,就稱這個應用程序是多線程應用程序,每個線程在棧區中都有自己的執行空間,自己的方法區、自己的變量。

jvm在啟動的時,首先有一個主線程,負責程序的執行,調用的是main函數。主線程執行的代碼都在main方法中。

當產生垃圾時,收垃圾的動作,是不需要主線程來完成,因為這樣,會出現主線程中的代碼執行會停止,會去運行垃圾回收器代碼,效率較低,所以由單獨一個線程來負責垃圾回收。

 

隨機性的原理:因為cpu的快速切換造成,哪個線程獲取到了cpu的執行權,哪個線程就執行。

 

返回當前線程的名稱:Thread.currentThread().getName()

線程的名稱是由:Thread-編號定義的。編號從0開始。

線程要運行的代碼都統一存放在了run方法中。

 

線程要運行必須要通過類中指定的方法開啟。start方法。(啟動后,就多了一條執行路徑)

start方法:1)、啟動了線程;2)、讓jvm調用了run方法。

 

創建線程的第一種方式:繼承Thread ,由子類復寫run方法。

步驟:

1,定義類繼承Thread類;

2,目的是復寫run方法,將要讓線程運行的代碼都存儲到run方法中;

3,通過創建Thread類的子類對象,創建線程對象;

4,調用線程的start方法,開啟線程,並執行run方法。

 

線程狀態:

被創建:start()

運行:具備執行資格,同時具備執行權;

凍結:sleep(time),wait()notify()喚醒;線程釋放了執行權,同時釋放執行資格;

臨時阻塞狀態:線程具備cpu的執行資格,沒有cpu的執行權;

消亡:stop()

 

 

創建線程的第二種方式:實現一個接口Runnable

步驟:

1,定義類實現Runnable接口。

2,覆蓋接口中的run方法(用於封裝線程要運行的代碼)。

3,通過Thread類創建線程對象;

4,將實現了Runnable接口的子類對象作為實際參數傳遞給Thread類中的構造函數。

為什么要傳遞呢?因為要讓線程對象明確要運行的run方法所屬的對象。

5,調用Thread對象的start方法。開啟線程,並運行Runnable接口子類中的run方法。

Ticket t = new Ticket();

/*  直接創建Ticket對象,並不是創建線程對象。

  因為創建對象只能通過new Thread類,或者new Thread類的子類才可以。

  所以最終想要創建線程。既然沒有了Thread類的子類,就只能用Thread類。

*/

Thread t1 = new Thread(t); //創建線程。

 

/*  只要將t作為Thread類的構造函數的實際參數傳入即可完成線程對象和t之間的關聯

  為什么要將t傳給Thread類的構造函數呢?其實就是為了明確線程要運行的代碼run方法。

*/

t1.start();

 

為什么要有Runnable接口的出現?

1通過繼承Thread類的方式,可以完成多線程的建立。但是這種方式有一個局限性,如果一個類已經有了自己的父類,就不可以繼承Thread類,因為java單繼承的局限性。

可是該類中的還有部分代碼需要被多個線程同時執行。這時怎么辦呢?

只有對該類進行額外的功能擴展,java就提供了一個接口Runnable。這個接口中定義了run方法,其實run方法的定義就是為了存儲多線程要運行的代碼。

所以,通常創建線程都用第二種方式。

因為實現Runnable接口可以避免單繼承的局限性。

 

2其實是將不同類中需要被多線程執行的代碼進行抽取。將多線程要運行的代碼的位置單獨定義到接口中。為其他類進行功能擴展提供了前提。

所以Thread類在描述線程時,內部定義的run方法,也來自於Runnable接口。

 

實現Runnable接口可以避免單繼承的局限性。而且,繼承Thread,是可以對Thread類中的方法,進行子類復寫的。但是不需要做這個復寫動作的話,只為定義線程代碼存放位置,實現Runnable接口更方便一些。所以Runnable接口將線程要執行的任務封裝成了對象

-------------------------------------------------------

//如:

new Thread(new Runnable(){  //匿名

public void run(){

System.out.println("runnable run");

}

})

{

public void run(){

System.out.println("subthread run");

}

}.start(); 

//結果:subthread run

---------------------------------------------------------

Try {

Thread.sleep(10);

}catch(InterruptedException e){}// 當刻意讓線程稍微停一下,模擬cpu切換情況。

 

多線程安全問題的原因

通過圖解:發現一個線程在執行多條語句時,並運算同一個數據時,在執行過程中,其他線程參與進來,並操作了這個數據。導致到了錯誤數據的產生。

 

涉及到兩個因素:

1,多個線程在操作共享數據。

2,有多條語句對共享數據進行運算。

原因:這多條語句,在某一個時刻被一個線程執行時,還沒有執行完,就被其他線程執行了。

 

解決安全問題的原理

只要將操作共享數據的語句在某一時段讓一個線程執行完,在執行過程中,其他線程不能進來執行就可以解決這個問題。

 

如何進行多句操作共享數據代碼的封裝呢?

java中提供了一個解決方式:就是同步代碼塊。

格式:

synchronized(對象)  // 任意對象都可以。這個對象就是鎖。

需要被同步的代碼;

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM