讀書筆記,簡單記錄....(都是從我的有道雲筆記直接複制的,沒有進行發表修改, 讀者見諒!)
第一章
掌握線程的啟動 暫停 停止 優先級 安全性等
1.1程序 與 線程
程序 作業系統結構的基礎,是一次程式的執行,是系統進行資源配置設定和排程的獨立機關,簡單了解:一個運作的exe程式就是一個程序
線程 可了解成程序中獨立運作的子任務。 使用多線程可以在同一時間内運作更多不同類型的任務
單任務的特點就是排隊執行,即同步。使用多線程就是在使用異步,多線程是異步的。
1.2 多線程實作
1.繼承Thread類
缺點:無法多繼承
public class Mythread extends Thread{
@override
public void run(){
super.run();
syso("mythread---");
}
}
main(){
Mythread s = new Mythread();
s.start(); //啟動線程
syso("-----main完")
}
2.實作Runnable接口
其實Thread也繼承了Runnable接口,他們之間有多态的關系
public class Myrun implements Runnable{
@override
public void run(){
syso("Myrun ---");
}
}
main(){
Myrun my = new Myrun ();
Thread s = new Thread(my);
s.start(); //啟動線程
syso("-----main完")
}
啟動線程:
調用start()方法,異步執行,使用多線程,代碼執行結果與代碼調用順序是無關的
若是直接調用run()方法,就不是異步執行,與調用普通方法無異。
執行個體變量與安全性
自定義線程類中的執行個體變量針對其他線程可以有共享與不共享之分,
1.不共享資料的情況
2.共享資料的情況
在某些jvm中,i-- 的操作要分成如下3步:
l )取得原有 i 值。
2 )計算 i-1。
3.對 i 指派
在這3個步驟中, 如果有多個線程同時通路, 那麼一定會出現非線程安全問題。
解決辦法就是 同步 synchronized 使多個線程在執行run方法時, 以排隊的方式進行處理。當一個線程調用run前, 先判斷m方法有沒有被上鎖, 如果上鎖, 說明有其他線程正在調用m方法, 必須等其他線程對run方法調用結束後才可以執行 run方法。這個線程就會不斷嘗試拿這把鎖, 直到能夠拿到為止, 而且是有多個線程 同時去争搶這把鎖
synchronized可以在任意對象及方法上加鎖, 而加鎖的這段代碼稱為 “互斥區” 或 “臨界區”。
非線程安全主要是指多個線程對同一個對象中的同一個執行個體變量進行操作時會出現值被更改、 值不同步的情況, 進而影響程式的執行流程
println()方法在内部是同步的, i-- 的操作卻是在進入print In()之前發生的,應該加同步
1.3一些方法
currentThread()方法
可傳回代碼段正在被哪個錢程調用的資訊
isAlive()方法
判斷目前的線程是否處于活動狀态。活動狀态就是線程已經啟動且尚未終止。但此值是不準确的。
sleep()方法
作用是在指定的毫秒數内讓目前“正在執行的線程”休眠(暫停執行)。“正在執行的線程”是指this.currentThread()傳回的線程。
getld()方法
取得線程的唯一辨別。
1.4停止線程
停止一個線程可以使用Thread.stop()方法,但最好不用它。雖然它确實可以停止一個正在運作的線程,但是這個方法是不安全的(unsafe),而且是已被棄用廢棄的(deprecated),在将來的Java版本中,這個方法将不可用或不被支援。
大多數停止一個線程的操作使用Thread.interrupt()方法,盡管方法的名稱是“停止,中的意思,但這個方法不會終止一個正在運作的線程,還需要加入一個判斷才-可以完成線
在Java中有以下3種方法可以終止正在運作的線程:
l )使用退出标志,使線程正常退出,也就是當run方法完成後線程終止。
2)使用stop方法強行終止線程,但是不推薦使用這個方法,因為stop和suspend及resume一樣,都是廢棄過期的方法,使用它們可能産生不可預料的結果
3)使用interrupt方法中斷線程。
stop()會強制停止,使一些清理性工作無法完成。會釋放鎖,可能造成資料不同步。調用stop會抛出java.lang.ThreadDeath異常,通常不捕獲。
intenrupt()方法僅僅是在目前線程中打了一個停 止的标記,并不是真的停止線程。
判斷線程是否是停止狀态
l ) this.interrupted(): 測試目前線程是否已經中斷。具有清理狀态的功能,連續2次調用
2 ) this. islnterrupted():該方法不是static的 測試線程是否已經中斷,不清除狀态标志
1.抛異常方式停止
先判斷線程是否停止,根據判斷條件來停止線程,,,出現異常時,鎖會自動釋放。

2.使用return停止線程
停止睡眠的線程
try catch 中,如果在sleep狀态下停止某一線程,會進入catch語句,并且清除 停止狀态值.使之變成false。java. lang. IncerrupdExcepcion:’sleep interrnpced
暫停 / 恢複線程
suspend()方法暫 停線程,過期方法
resume()方法恢複線程的執行。過期方法
缺陷:獨占,不同步
1.如果使用不當,極易造成公共的同步對象的獨占,使其他線程無法通路公共同步對象。如:當程式運作到println()方法内部停止時,同步鎖未被釋放,這導緻目前PrintStrearn對象的println()方法一直呈“暫停”狀态,并且“鎖未釋放
2.
yield方法
放棄目前的 CPU 資源. 将它讓給其他的任務去占用 CPU 執行時間。 但放棄的時間不确定, 有可能剛剛放棄, 馬上又獲得 CPU 時間片。
1.5線程優先級
線程可以劃分優先級,優先級較高的線程得到的CPU資源較多,也就是CPU優先執行優先級較高的線程對象中的任務。設定線程優先級有助于幫“線程規劃器”确定在下一次選擇哪一個線程來優先執行。
設定線程的優先級
setPriority()方法,此方法在JDK的源代碼如下:
優先級的繼承特性
線程的優先級具有繼承性,比如A線程啟動B線程則B線程的優先級與A是一樣的。
優先級具有規則性
高優先級的線程總是大部分先執行完, 但不代表高優先級的線程全部先執行完,誰先執行完和代碼的調用順序無關
優先級具有随機性
優先級較高的線程不一定每一次都先執行完。
1.6守護線程
Java線程中有兩種線程,一種是使用者線程,另一種是守護線程。
守護線程是一種特殊的線程,它的特性有“陪伴”的含義,當程序中不存在非守護線程了,則守護線程自動銷毀。
典型的守護線程就是垃圾回收線程,當程序中沒有非守護線程了,則垃圾回收線程也就沒有存在的必要了,自動銷毀。
第二章 對象及變量的并發通路
“非線程安全” 其實會在多個線程對同一個對象中的執行個體變量進行并發通路時發生, 産生的後果就是 “髒讀”,也就是取到的資料其實是被更改過的。
方法内的變量是線程安全的
非線程安全”問題存在于“執行個體變量”中,如果是方法内部的私有變量,則永遠是“線程安全”的。
1.synchronized
用線程通路的對象中如果有多個執行個體變量, 則運作的結果有可能出現交叉的情況,方法前加同步即可。synchronized可以使多個線程通路同一個資源具有同步性, 而且它還具有将線程工作記憶體中的私有變量與公共記憶體中的變量同步的功能,即具有volatile同步的功能。
它包含兩個特征:互斥性和可見性
在兩個線程通路同一個對象中的同步方法時一定是線程安全的
1.synchronized同步方法
1.多個對象多個鎖
兩個線程分别通路同一個類的兩個不同執行個體的相同名稱的同步方法,效果是以異步的方式運作的,
關鍵字synchronized取得的鎖都是對象鎖 ,因為new一個執行個體産生了一個鎖。鎖不統一。
一些結論
1.線程A先持有了object對象的鎖,但線程B完全可以異步調用非synchronized類型的方法。
2. A線程先持有o對象的Lock鎖,B線程如果在這時調用o對象中的synchronized 類型的方法則需等待,也就是同步。
髒讀
多個線程調用同一個方法時, 為了避免資料出現交叉的情況,使用synchronized關鍵字來進行同步。
問題:get 和set 其中一個加同步時,如在指派時進行了同步, 但在取值時有可能出現一些意想不到的意外, 這種情況就是髒讀( dirty Read)。 發生髒讀的情況是在讀取執行個體變量時, 此值已經被其他線程更改過了。原因是get方法沒有同步
解決方法:set get都加同步
鎖重入
synchronized擁有鎖重人的功能,也就是在使用synchronized時,當一個線程 得到一個對象鎖後,再次請求此對象鎖時是可以再次得到該對象的鎖的。這也證明在一個 Synchronized方法/塊的内部調用本類的其他synchronized方法/塊時,是永遠可以得到鎖的。
“可重人鎖” 的概念是:自己可以再次擷取自己的内部鎖。如有l條線程獲得了某個對象的鎖, 此時這個對象鎖還沒有釋放, 當其再次想要擷取這個對象的鎖的時候還是可以擷取的, 如果不可鎖重人的話, 就會造成死鎖。
存在繼承時:當存在父子類繼承關系時,子類是完全可以通過可重人鎖調用父類的同步方法的。
同步不具有繼承性
同步不能繼承,父類方法加同步時,若調用子類方法還得在子類的方法中添加synchronized關鍵,才能確定安全。
2. synchronized同步語句塊
synchronized聲明方法在某些情況下是有弊端的,若執行時間過長,會造成長時間等待。可以使用 synchronized同步語句塊來解決。
synchronized(this)代碼塊是鎖定目前對象的
結論:
1.兩個并發線程通路同一對象中的synchronized(this)同步代碼塊時,一段時間内隻能有一個線程被執行,另一線程必須等待目前線程執行完代碼塊以後才能執行該代碼塊。
2.當一個線程通路object的一 個synchronized同步代 碼塊時, 另一線程仍可以通路該object對象中的非synchronized(this)同步代碼塊。
3.當一個線程通路object的一個 synchronjzed(this)同步代碼塊時,其他線程對同一個object中所有其他synchronized(this)同 步代碼塊的通路将被阻塞,這說明synchronized使用的“對象螢幕”是一個。
不在synchronized塊中就是異步執行, 在synchronized塊中就是同步執行。
将任意對象作為對象螢幕
多個線程調用同一個對象中的不同名稱的 synchronized同步方法或 synchronized(this)同 步代碼塊時, 調用 的效果就是按順序執行, 也就是同步的, 阻塞的。
這說明 synchronized同步方法或 synchronized(th.is)同步代碼塊分别有兩種作用。
( I ) synchronized同步方法
l )對其他 synchronized同步方法或 synchronized(this)同步代碼塊調用呈阻塞狀态。
2 )同一時間隻有一個線程可以執行 synchronized同步方法中的代碼。
( 2 ) synchronized(由is)同步代碼塊
I )對其他 synchronized同步方法或 synchronized(this)同步代碼塊調用呈阻塞狀态。
2 )同一時間隻有一個線程可以執行synchronized(this)同步代碼塊中的代碼。
使用 synchronized(th.is)格式來同步代碼塊, 其實Java 還支援對 “任意對象” 作為 對象螢幕 來實作同步的功能。 這個 任意對象” 大多數是執行個體變量及方法的參數, 使用格式為 synchronized(非 this對象)。
根據前面對 synchronized(this)同步代碼塊的作用總結可知,
synchronized(非 this對象)格式的作用隻有 l 種: synchronized(非 this對象)同步代碼塊
非this對象鎖具有一定的優點:如果在一個類中有很多個synchronized方法,雖然能實作同步,但會受到阻塞,是以影響運作效率;
但如果使用同步代碼塊鎖非this對象,則synchronized(非this)代碼塊中的程式與同步方法是異步的,不與其他鎖this同步方法争搶this鎖,則可大大提高運作效率。
對象螢幕不同,運作結果也是異步的。
“synchronized(非this對象x)” 格式的寫法是将 x對象本身作為 “對象螢幕” ,這樣就可以得出以下 3 個結論:
1 )當多個線程同時執行synchronized(x) {}同步代碼塊時呈同步效果。
2) 當其他線程執行x對象中synchronized同步方法時呈同步效果。
3) 當其他線程執行x對象方法裡面的synchronized(this)代碼塊時也呈現同步效果。
但需要注意:如果其他線程調用不加synchronized關鍵字的方法時, 還是異步調用
3.靜态同步synchronized方法與synchronized(xxx.class)代碼塊
synchronized應用在static靜态方法上,這樣寫是對目前的*.java檔案對應的Class類進行持鎖,Class鎖可以對類的所有對象執行個體起作用。同步synchronized(xx.class)代碼塊的作用其實和synchronized static方法的作用一樣。
synchronized關鍵字加到非static靜态方法上是給對象上鎖。
4.String類型資料的常量池特性
在 JVM 中具有 String 常量池緩存的功能,将 synchronized(string)同步塊與 String 聯合使用時, 要注意常量池以帶來的一些例外。如取到的鎖相同造成一個線程不能執行。
大多數的情況下, 同步synchronized 代碼塊都不使用 String 作為鎖對象, 而改用其他, 比如 new Object()執行個體化Object 對象, 但它并不放入緩存中。
5.死循環
同步方法容易造成死循環
如下圖:線程B永遠得不到運作的機會,鎖死了。
解決方法: 可以使用同步塊來解決這樣的問題。。下下圖
6.死鎖
不同的線程都在等待根本不可能被釋放的鎖 進而導緻所有的任務都無法繼續完成,造成線程的 “假死” 。在設計程式時就要避免雙方互相持有對方的鎖的情況。
最經典的嵌套造成死鎖
使用JDK自帶的工具來監測是否有死鎖的現象。 首先進入CMD工具, 再進入JDK的安裝檔案夾中的bin目錄,執行jps指令,得到運作的線程Run的id值是3244。 再執行jstack指令, 檢視結果。
7.内置類與靜态内置類
1.在内置類中有兩個同步方法,但使用的卻是不同的鎖,列印的結果 也是異步的。
2.同步代碼塊synchronized(class2)對class2上鎖後,其他線程隻能以同步的方式調用class2中的靜态同步方法
8.鎖對象的改變
隻要對象不變,既使對象的屬性被改變,運作的結果還是同步
如 果同時持有相同的鎖對象, 則這些線程之間就是同步的;如果分别獲得鎖對象, 這些線程之 間就是異步的。
2.volatile關鍵字
volatile的主要作用是使變量在多個線程間可見。強制的從公共記憶體中讀取變量 的值
2.1關鍵字volatile與死循環
停不下來的原因主要就是main線程 一直在處理while()循環,條件一直成立.導緻程式不能繼續執行後面的代碼。解決的辦法當然是用多線程技術。(讓另一個線程改變條件)
是什麼原因造成将jvm設定為-server時就出現死循環呢?
在啟動RunThread.java線程時, 變量private boolean isRunning = true;存在于公共堆棧及線程 的私有堆棧中。 在jvm被設定為-server模式時,為了線程運作的效率, 線程一直在私有堆棧 中取得isRunning的值是 true。 而代碼 thread.setRunning( false);,雖然被執行, 更新的卻是公共堆棧中的isRunning變量值false, 是以一 直就是死循環的狀态。
問題其實就是私有堆戰中的值和公共堆桔中的值不同步造成的,解決這樣的問題就要使用volatile關鍵字了,它主要的作用就是當線程通路isRunning這個變量時,強制性從公 共堆戰中進行取值。
2.2 synchronized與volatile進行一下比較:
volatile關鍵字特點 增加了執行個體變量在多個線程之間的可見性。 但最緻命 的缺點是不支援原子性,即不具備同步性,
l )關鍵字volatile是線程同步的輕量級實作, 是以volatile性能肯定比synchronized要好。并且volatile隻能修飾于變量,而synchronized可以修飾方法, 以及代碼塊。 随着JDK新版本的釋出,synchronized關鍵字在執行效率上得到很大提升, 在開發中使用synchronized 關鍵字的比率還是比較大的。
2) 多錢程通路volatile不會發生阻塞,而synchronized會出現阻塞。
3) volatile能保證資料的可見性, 但不能保證原子性;
synchronized可以保證原子性,也可以間接保證可見性, 因為它會将私有記憶體和公共記憶體中的資料做同步。使用synchronized同步關鍵字也就沒有必要再使用volatile關鍵字來聲明變量了。
4.關鍵字volatile解決的是變量在多個線程之間的可見性;而synchronized關鍵字解決的是多個線程之間通路資源的同步性。
但在這裡需要注意 的是: 如果修改執行個體變量中的資料, 比如i++, 也就是 i=i十l, 則這樣的操作其實’并不是原子操作, 也就是非線程安全的。 表達式i++的操作步驟分解如下:
l )從記憶體中取出 i 的值
2)計算 i的值;
3) 将 i 的值寫到記憶體中
假如在第2步計算值的時候, 另外一個線程也修改 i的值, 那麼這個時候就會出現髒資料。解決的辦法其實就是使用 synchronized關鍵字
變量在記憶體中的工作過程
在多線程環境中,use和assign是多次出現的,但這一操作并不是原子性,也就是在 read和load之後,如果主記憶體count變量發生修改之後,線程工作記憶體中的值由于已經加載,不會産生對應的變化,也就是私有記憶體和公共記憶體中的變量不同步,也就出現了非線程安全問題。
2.3 使用原子類進行i++操作
除了在i++操作時使用synchronized關鍵字實作同步外,還可以使用Atomiclnteger原子
類進行實作。原子操作是不能分割的整體,沒有其他線程能夠中斷或檢查正在原子操作中的變量。一個原子(atomic)類型就是一個原子操作可用的類型,它可以在沒有鎖的情況下做到線程安全。
但也不完全安全。原子類在具有有邏輯性的情況下輸出結果也具有随機性。
addAndGet()方法是原子的,但方法和方法之間的調用卻不是原子的。解決這樣的問題必須要用同步。
第三章 線程間通信-----------------
待更..........