溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

什么是java多線程

發(fā)布時間:2021-06-24 14:01:29 來源:億速云 閱讀:123 作者:chen 欄目:大數(shù)據(jù)

本篇內(nèi)容主要講解“什么是java多線程”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“什么是java多線程”吧!

線程聲明周期

線程的五個狀態(tài):新建,就緒,運行,阻塞,死亡。 其中就緒和運行兩個狀態(tài)客戶互相轉(zhuǎn)換,但運行到阻塞,阻塞到就緒,只能單向轉(zhuǎn)換。

剛new出的線程就是【新建】狀態(tài),調(diào)用start之后就是就【緒狀】態(tài),獲取CUP資源并執(zhí)行后就是【運行】狀態(tài),CUP用完/sleep()/調(diào)用阻塞IO/被suspend()掛起/正在獲取其他線程同步監(jiān)視器/等待通知等這些行為都有可能讓線程從【運行】進入【阻塞】狀態(tài)。

創(chuàng)建線程三種方式及對比
  • 繼承Thread類創(chuàng)建線程
    需要寫Thread的子類,并重寫其中的線程執(zhí)行體run()方法,通過start()方法來啟動線程。

  • 實現(xiàn)Runable接口創(chuàng)建線程類
    需要在實現(xiàn)類中重寫run()方法,實現(xiàn)類的實例將做為target對象,通過new Thread(target, "thread name").start()啟動線程。

  • 使用Callable接口結(jié)合Future接口
    Callable中的call()方法作為線程執(zhí)行體,F(xiàn)uture的實現(xiàn)類FutureTask(同時實現(xiàn)了Runable)的實例作為target,初始化FutureTask時傳入Callable實例,通過new Thread(target,"thread name").start()啟動線程。

優(yōu)劣對比

  • 采用繼承Thread類的方法編程相對簡單,但無法再繼承別的類,且多個線程之間無法共享變量。

  • 采用Runable接口方法可以同時繼承其他類,但是無法獲取線程的返回值,也不能拋出異常。

  • 采用Callable結(jié)合Future的方法雖然編程比較復雜,但是即不受繼承限制,又可以獲取多線程的返回值,還能拋出異常,因此是最常用的實現(xiàn)多線程的方法。

控制線程

join()等待別的線程:在某個線程中調(diào)用其他線程的join()方法,就會讓當前線程進入阻塞,直到被join線程執(zhí)行完畢。通常會在主線程中調(diào)用join()方法,這樣可以保證所有子線程都結(jié)束了,主線程才結(jié)束。

setDaemon():在start()之前調(diào)用線程自身的setDatemon()可以設(shè)置成后臺線程:如果所有前臺線程都死亡,后臺線程會自動死亡。

sleep(): 通過Thread.sleep() 可以讓當前線程進入【睡眠】狀態(tài),在睡眠時間到達之前,即使有可用CUP,線程也無法執(zhí)行,醒來的線程也只能進入就【緒狀】態(tài)。

yield():通過Thread.yield()可以設(shè)置線程的優(yōu)先級(用數(shù)字或者常量),使線程進入【就緒】狀態(tài),相當于暫停線程。只有優(yōu)先級等于或高于當前線程的線程,才有可能獲取CUP資源執(zhí)行,否則當前線程將繼續(xù)執(zhí)行。

線程同步

是為了解決經(jīng)典的生產(chǎn)者消費者問題(保證事務(wù)處理的原子性,例如多個線程向同一個賬戶存錢取錢,存錢和取錢各自都需要是一個原子操作)。

線程同步的方法,

  • 同步代碼塊。即將需要同步的代碼放在 synchronized(obj){}的大括號中,使得線程要執(zhí)行同步代碼塊之前,需要先獲取同步監(jiān)視器(的鎖定),執(zhí)行完之后,需要釋放同步監(jiān)視器。

  • 同步方法。使用synchronized修飾整個方法(不能修飾static方法),同步監(jiān)視器就是this,當在線程執(zhí)行體run()或call()中調(diào)用這個方法的時候,需要獲取到同步監(jiān)視器的鎖定(即同步方法所在類的實例)的線程才能執(zhí)行同步方法。
    注意sleep(), yield(), suspend()方法并不會釋放同步監(jiān)視器。

  • 同步鎖。最常用的ReentrantLock鎖,是一種更靈活的同步方式,線程需要先加鎖,之后加鎖成功的線程才能執(zhí)行代碼,之后需要解鎖。使用try ... finally 可以保證鎖釋放。

死鎖

兩個線程互相等待對方(釋放同步監(jiān)視器),就會進入死鎖。

例如線程1線鎖定A對象,接著睡眠,線程2鎖定B對象,也睡眠,然后線程A醒來,如果此時去請求B對象監(jiān)視器,A將被阻塞,如果B醒來也去請求A監(jiān)視器,B也將阻塞,并且A和B此時各自持有一個監(jiān)視器又在互相請求對方監(jiān)視器,將進入死鎖。

 線程通信

線程通信可以保證線程執(zhí)行的先后順序。

通常有三種通信方式,

  • 傳統(tǒng)的線程通信,使用wait(), nofity(),nitifyAll(),適用于使用同步代碼塊和同步方法的同步線程中。

  • 使用lock對象返回的condition對象控制線程通信。condition也包含三個方法,await(),signal(),signalAll()。 condition方法使用與使用lock進行線程同步的情況中。

  • 使用阻塞隊列(BlockingQueue)控制線程通信。其特征是,當隊列滿的時候,生產(chǎn)者線程阻塞,此時只有消費者線程能執(zhí)行代碼;當隊列空的時候,消費者線程將阻塞,此時只有生產(chǎn)者線程能執(zhí)行代碼。在線程非空且未滿的時候,生產(chǎn)者和消費者都可以執(zhí)行。這種方式更靈活,能通過隊列容量控制線程切換。

到此,相信大家對“什么是java多線程”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學習!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI