本篇內容主要講解“什么是java多線程”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“什么是java多線程”吧!
線程的五個狀態:新建,就緒,運行,阻塞,死亡。 其中就緒和運行兩個狀態客戶互相轉換,但運行到阻塞,阻塞到就緒,只能單向轉換。
剛new出的線程就是【新建】狀態,調用start之后就是就【緒狀】態,獲取CUP資源并執行后就是【運行】狀態,CUP用完/sleep()/調用阻塞IO/被suspend()掛起/正在獲取其他線程同步監視器/等待通知等這些行為都有可能讓線程從【運行】進入【阻塞】狀態。
繼承Thread類創建線程
需要寫Thread的子類,并重寫其中的線程執行體run()方法,通過start()方法來啟動線程。
實現Runable接口創建線程類
需要在實現類中重寫run()方法,實現類的實例將做為target對象,通過new Thread(target, "thread name").start()啟動線程。
使用Callable接口結合Future接口
Callable中的call()方法作為線程執行體,Future的實現類FutureTask(同時實現了Runable)的實例作為target,初始化FutureTask時傳入Callable實例,通過new Thread(target,"thread name").start()啟動線程。
優劣對比
采用繼承Thread類的方法編程相對簡單,但無法再繼承別的類,且多個線程之間無法共享變量。
采用Runable接口方法可以同時繼承其他類,但是無法獲取線程的返回值,也不能拋出異常。
采用Callable結合Future的方法雖然編程比較復雜,但是即不受繼承限制,又可以獲取多線程的返回值,還能拋出異常,因此是最常用的實現多線程的方法。
join()等待別的線程:在某個線程中調用其他線程的join()方法,就會讓當前線程進入阻塞,直到被join線程執行完畢。通常會在主線程中調用join()方法,這樣可以保證所有子線程都結束了,主線程才結束。
setDaemon():在start()之前調用線程自身的setDatemon()可以設置成后臺線程:如果所有前臺線程都死亡,后臺線程會自動死亡。
sleep(): 通過Thread.sleep() 可以讓當前線程進入【睡眠】狀態,在睡眠時間到達之前,即使有可用CUP,線程也無法執行,醒來的線程也只能進入就【緒狀】態。
yield():通過Thread.yield()可以設置線程的優先級(用數字或者常量),使線程進入【就緒】狀態,相當于暫停線程。只有優先級等于或高于當前線程的線程,才有可能獲取CUP資源執行,否則當前線程將繼續執行。
是為了解決經典的生產者消費者問題(保證事務處理的原子性,例如多個線程向同一個賬戶存錢取錢,存錢和取錢各自都需要是一個原子操作)。
線程同步的方法,
同步代碼塊。即將需要同步的代碼放在 synchronized(obj){}的大括號中,使得線程要執行同步代碼塊之前,需要先獲取同步監視器(的鎖定),執行完之后,需要釋放同步監視器。
同步方法。使用synchronized修飾整個方法(不能修飾static方法),同步監視器就是this,當在線程執行體run()或call()中調用這個方法的時候,需要獲取到同步監視器的鎖定(即同步方法所在類的實例)的線程才能執行同步方法。
注意sleep(), yield(), suspend()方法并不會釋放同步監視器。
同步鎖。最常用的ReentrantLock鎖,是一種更靈活的同步方式,線程需要先加鎖,之后加鎖成功的線程才能執行代碼,之后需要解鎖。使用try ... finally 可以保證鎖釋放。
兩個線程互相等待對方(釋放同步監視器),就會進入死鎖。
例如線程1線鎖定A對象,接著睡眠,線程2鎖定B對象,也睡眠,然后線程A醒來,如果此時去請求B對象監視器,A將被阻塞,如果B醒來也去請求A監視器,B也將阻塞,并且A和B此時各自持有一個監視器又在互相請求對方監視器,將進入死鎖。
線程通信可以保證線程執行的先后順序。
通常有三種通信方式,
傳統的線程通信,使用wait(), nofity(),nitifyAll(),適用于使用同步代碼塊和同步方法的同步線程中。
使用lock對象返回的condition對象控制線程通信。condition也包含三個方法,await(),signal(),signalAll()。 condition方法使用與使用lock進行線程同步的情況中。
使用阻塞隊列(BlockingQueue)控制線程通信。其特征是,當隊列滿的時候,生產者線程阻塞,此時只有消費者線程能執行代碼;當隊列空的時候,消費者線程將阻塞,此時只有生產者線程能執行代碼。在線程非空且未滿的時候,生產者和消費者都可以執行。這種方式更靈活,能通過隊列容量控制線程切換。
到此,相信大家對“什么是java多線程”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。