更新時間:2019-12-23 14:31:27 來源:動力節點 瀏覽2309次
多線程
提高了程序的執行效率,多線程同時執行,因此具有不確定性
提高了資源利用率,CPU、內存等
占用一定的內存空間
線程越多CPU的調度開銷越大
程序的復雜度會上升
線程池
避免線程的創建和銷毀帶來的性能開銷(少開銷)
加快響應速度。任務到達時不用創建線程,直接使用線程池中的
避免大量的線程間因互相搶占系統資源而阻塞的現象(避免阻塞)
能對線程進行簡單的管理并提供定時執行、間隔執行等功能(便于管理)
sleep和wait
sleep是使線程停止一段時間的方法,線程不會釋放對象鎖.在sleep一段時間后,線程不一定立刻回復執行
wait是線程交互的時候,如果線程對一個同步對象發出wait調用,該線程會立刻暫停執行.進入等待狀態,直到被喚醒,線程會放棄對象鎖,使得其他線程可以使用同步控制塊或者方法
多線程和并發
run和start的區別:
調用 start() 方法才會啟動新線程;如果直接調用 Thread 的 run() 方法,它的行為就會和普通的方法一樣;為了在新的線程中執行我們的代碼,必須使用 Thread.start() 方法。run只是thread的一個普通方法,start是真正的啟一個線程
關鍵字
可見性
可見性,是指線程之間的可見性,一個線程修改的狀態對另一個線程是可見的.也就是一個線程修改的結果。另一個線程馬上就能看到
在 Java 中 volatile、synchronized 和 final 實現可見性
原子性
將操作變成原子操作
在 Java 中 synchronized 和在 lock、unlock 中操作保證原子性
有序性
Java 語言提供了 volatile 和 synchronized 兩個關鍵字來保證線程之間操作的有序性
wait和sleep
sleep
在指定的毫秒數內讓當前正在執行的線程休眠(暫停執行),該線程不丟失任何監視器的所屬權,sleep() 是 Thread 類專屬的靜態方法,針對一個特定的線程。
wait
方法使實體所處線程暫停執行,從而使對象進入等待狀態,導致線程進入等待狀態,直到它被其他線程通過notify()或者notifyAll喚醒,該方法只能在同步方法中調用。
比較
本質的區別:sleep是線程的運行狀態控制,wait是線程之間的通訊
sleep是Thread中的方法,wait是Object中的方法
wait() 方法進入等待狀態時會釋放同步鎖。調用的時候需要先獲得該 Object 的鎖,調用 wait 后,會把當前的鎖釋放掉同時阻塞住。而 sleep() 方法不會釋放同步鎖。
sleep讓線程從運行到阻塞,wait讓線程從運行到等待隊列
wait要用notify和notify喚醒,只能在同步環境中使用,sleep可以在任何環境中使用
notify notifyall
notify
隨機選擇一個在該對象上調用wait方法的線程,解除其阻塞狀態,該方法只能在同步方法或同步塊內部調用。
notifyall
解除所有那些在該對象上調用wait方法的線程的阻塞狀態,同樣該方法只能在同步方法或同步塊內部調用。
synchronized
是一種同步鎖(CPU悲觀鎖),java并發編程的最常用的用于保證線程安全的方式,所有加上 synchronized 的方法和塊語句,在多線程訪問的時候,同一時刻只能有一個線程能夠訪問。
修飾實例方法
作用于當前實例加鎖,進入同步代碼前要獲得當前實例的鎖。
實例方法不包括靜態方法
修飾靜態方法
作用于當前類對象加鎖,進入同步代碼前要獲得當前類對象的鎖。靜態成員不專屬于任何一個實例對象,是類成員,因此通過class對象鎖可以控制靜態成員的并發操作
修飾代碼塊
指定加鎖對象,對給定對象加鎖,進入同步代碼庫前要獲得給定對象的鎖。
Lock
采用樂觀鎖
能完成synchronized所實現的所有功能,Lock有比synchronized更精確的線程語義和更好的性能。Lock的鎖定是通過代碼實現的,而synchronized是在JVM層面上實現的,synchronized會自動釋放鎖,而Lock一定要求程序員手工釋放,并且必須在finally從句中釋放。Lock還有更強大的功能,例如,它的tryLock方法可以非阻塞方式去拿鎖。Lock鎖的范圍有局限性,塊范圍,而synchronized可以鎖住塊、對象、類。在加鎖和解鎖處需要通過lock()和unlock()顯示指出
volatile
Volatile 變量具有 synchronized 的可見性特性,但是不具備原子特性。volatile 是一個特殊的修飾符,只有成員變量才能使用它。在Java并發程序缺少同步類的情況下,多線程對成員變量的操作對其它線程是透明的。volatile 變量可以保證下一個讀取操作會在前一個寫操作之后發生。線程都會直接從內存中讀取該變量并且不緩存它。這就確保了線程讀取到的變量是同內存中是一致的。
volatile
能保證可見性,不能保證原子性
當對非 volatile 變量進行讀寫的時候,每個線程先從內存拷貝變量到CPU緩存中。如果計算機有多個CPU,每個線程可能在不同的CPU上被處理,這意味著每個線程可以拷貝到不同的 CPU cache 中。而聲明變量是 volatile 的,JVM 保證了每次讀變量都從內存中讀,跳過 CPU cache 這一步。
輕量級的 synchronized
Volatile變量的同步性較差(但有時它更簡單并且開銷更低),而且其使用也更容易出錯。
volatile 并不完全是線程安全的
用volatile修飾的變量,線程在每次使用變量的時候,都會讀取變量修改后的值。volatile很容易被誤用,用來進行原子性操作。
訪問最新值
Volatile修飾的成員變量在每次被線程訪問時,都強迫從共享內存中重讀該成員變量的值。而不是從各個線程的“工作內存”。而且,當成員變量發生變化時,強迫線程將變化值回寫到共享內存。這樣在任何時刻,兩個不同的線程總是看到某個成員變量的同一個值。
效率問題
synchronized關鍵字是防止多個線程同時執行一段代碼,那么就會很影響程序執行效率,而volatile關鍵字在某些情況下性能要優于synchronized
volatile關鍵字是無法替代synchronized關鍵字的,因為volatile關鍵字無法保證操作的原子性。
JAVA高級
對象序列化
很多情況下,對象內部狀態是需要被持久化的,將運行中的對象狀態保存下來(最直接的方式就是保存到文件系統中),在需要的時候可以還原,即使是在Java虛擬機退出的情況下
對象序列化機制是Java內建的一種對象持久化方式,可以很容易實現在JVM中的活動對象與字節數組(流)之間進行轉換,使用得Java對象可以被存儲,可以被網絡傳輸,在網絡的一端將對象序列化成字節流,經過網絡傳輸到網絡的另一端,可以從字節流重新還原為Java虛擬機中的運行狀態中的對象
以上就是動力節點Java培訓機構小編介紹的“Java培訓教程:Java多線程并發教程”的內容,希望對大家有幫助,如有疑問,請在線咨詢,有專業老師隨時為你服務。
相關文章
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習