多線(xiàn)程

一些基礎(chǔ)概念
  • 程序(program):是為完成特定任務(wù)、用某種語(yǔ)言編寫(xiě)的一組指令的集合煌茴。即指一段靜態(tài)的代碼义辕,靜態(tài)對(duì)象

  • 進(jìn)程(process):是程序的一次執(zhí)行過(guò)程,或是正在運(yùn)行的一個(gè)程序现拒。是一個(gè)動(dòng)態(tài)的過(guò)程:有它自身的產(chǎn)生辣垒、存在和消亡的過(guò)程∮∈撸——生命周期

    • 進(jìn)程作為資源分配的單位勋桶,系統(tǒng)在運(yùn)行時(shí)會(huì)為每個(gè)進(jìn)程分配不同的內(nèi)存區(qū)域
  • 線(xiàn)程(thread):進(jìn)程可進(jìn)一步細(xì)化為線(xiàn)程,是一個(gè)程序內(nèi)部的一條執(zhí)行路徑.若一個(gè)進(jìn)程同一時(shí)間 并行執(zhí)行多個(gè)線(xiàn)程侥猬,就是支持多線(xiàn)程的.

    • 線(xiàn)程作為調(diào)度和執(zhí)行的單位例驹,每個(gè)線(xiàn)程擁有獨(dú)立的運(yùn)行棧和程序計(jì)數(shù)器(pc)
  • 并行與并發(fā)

    • 并行:多個(gè)CPU同時(shí)執(zhí)行多個(gè)任務(wù)

    • 并發(fā):一個(gè)CPU(采用時(shí)間片)同時(shí)執(zhí)行多個(gè)任務(wù)

Thread類(lèi)
構(gòu)造器
  • Thread() :創(chuàng)建新的Thread對(duì)象

  • Thread(String threadname): 創(chuàng)建線(xiàn)程并指定線(xiàn)程實(shí)例名

  • Thread(Runnable target) :指定創(chuàng)建線(xiàn)程的目標(biāo)對(duì)象,它實(shí)現(xiàn)了Runnable接 中的run方法

  • Thread(Runnable target, String name) :創(chuàng)建新的Thread對(duì)象

特性
  • 1.每個(gè)線(xiàn)程都是通過(guò)某個(gè)特定Thread對(duì)象的run()方法來(lái)完成操作的退唠,經(jīng)常把run()方法的主體稱(chēng)為 線(xiàn)程體

  • 通過(guò)該Thread對(duì)象的start()方法來(lái)啟動(dòng)這個(gè)線(xiàn)程鹃锈,而非直接調(diào)用run()

有關(guān)方法
  • void start(): 啟動(dòng)線(xiàn)程,并執(zhí)行對(duì)象的run()方法

  • run(): 線(xiàn)程在被調(diào)度時(shí)執(zhí)行的操作

  • String getName(): 返回線(xiàn)程的名稱(chēng)

  • void setName(String name):設(shè)置該線(xiàn)程名稱(chēng)

  • static Thread currentThread(): 返回當(dāng)前線(xiàn)程瞧预。在Thread子類(lèi)中就是this屎债,通常用于主線(xiàn)程和Runnable實(shí)現(xiàn)類(lèi)

  • static void yield(): 線(xiàn)程讓步,暫停當(dāng)前正在執(zhí)行的線(xiàn)程垢油,把執(zhí)行機(jī)會(huì)讓給優(yōu)先級(jí)相同或更高的線(xiàn)程盆驹,若隊(duì)列中沒(méi)有同優(yōu)先級(jí)的線(xiàn)程,忽略此方法

  • join() : 當(dāng)某個(gè)程序執(zhí)行流中調(diào)用其他線(xiàn)程的 join() 方法時(shí)秸苗,調(diào)用線(xiàn)程將被阻塞召娜,直到 join() 方法加入的 join 線(xiàn)程執(zhí)行完為止,低優(yōu)先級(jí)的線(xiàn)程也可以獲得執(zhí)行

  • static void sleep(long millis) :(指定時(shí)間:毫秒)惊楼,令當(dāng)前活動(dòng)線(xiàn)程在指定時(shí)間段內(nèi)放棄對(duì)CPU控制,使其他線(xiàn)程有機(jī)會(huì)被執(zhí)行,時(shí)間到后重排隊(duì)玖瘸。拋出InterruptedException異常

  • stop(): 強(qiáng)制線(xiàn)程生命期結(jié)束,不推薦使用

  • boolean isAlive(): 返回boolean檀咙,判斷線(xiàn)程是否還活著

創(chuàng)建線(xiàn)程的兩種方式
繼承Thread類(lèi)
  • 用法:

    • 1.定義子類(lèi)繼承Thread類(lèi)

    • 2.子類(lèi)中重寫(xiě)Thread類(lèi)中的run方法

    • 3.創(chuàng)建Thread子類(lèi)對(duì)象雅倒,即創(chuàng)建了線(xiàn)程對(duì)象

    • 4.調(diào)用線(xiàn)程對(duì)象start方法:?jiǎn)?dòng)線(xiàn)程,調(diào)用run方法

  • 說(shuō)明:

    • 1.如果自己手動(dòng)調(diào)用run()方法弧可,那么就只是普通方法蔑匣,沒(méi)有啟動(dòng)多線(xiàn)程模式

    • 2.run()方法由JVM調(diào)用,什么時(shí)候調(diào)用,執(zhí)行的過(guò)程控制都有操作系統(tǒng)的CPU 調(diào)度決定

    • 3.想要啟動(dòng)多線(xiàn)程裁良,必須調(diào)用start方法

    • 4.一個(gè)線(xiàn)程對(duì)象只能調(diào)用一次start()方法啟動(dòng)凿将,如果重復(fù)調(diào)用了,則將拋出以上 的異常IllegalThreadStateException

實(shí)現(xiàn)Runnable接口
  • 用法:

    • 1.定義子類(lèi)价脾,實(shí)現(xiàn)Runnable接口

    • 2.子類(lèi)中重寫(xiě)Runnable接口中的run方法

    • 3.通過(guò)Thread類(lèi)含參構(gòu)造器創(chuàng)建線(xiàn)程對(duì)象

    • 4.將Runnable接口的子類(lèi)對(duì)象作為實(shí)際參數(shù)傳遞給Thread類(lèi)的構(gòu)造器中

    • 5.調(diào)用Thread類(lèi)的start方法:開(kāi)啟線(xiàn)程牧抵,調(diào)用Runnable子類(lèi)的run方法

  • 好處

    • 1.避免了單繼承的局限性

    • 2.多個(gè)線(xiàn)程可以共享同一個(gè)接口實(shí)現(xiàn)類(lèi)的對(duì)象,非常適合多個(gè)相同的線(xiàn)程來(lái)處理同一份資源

線(xiàn)程的調(diào)度
調(diào)度策略
  • 時(shí)間片

  • 搶占式:高優(yōu)先級(jí)的線(xiàn)程搶占CPU

Java的調(diào)度方法
  • 同優(yōu)先級(jí)線(xiàn)程組成先進(jìn)先出隊(duì)列(先到先服務(wù))侨把,使用時(shí)間片策略

  • 對(duì)高優(yōu)先級(jí)犀变,使用優(yōu)先調(diào)度的搶占式策略

線(xiàn)程的優(yōu)先級(jí)
線(xiàn)程的優(yōu)先級(jí)等級(jí)
  • MAX_PRIORITY :10

  • MIN _PRIORITY :1

  • NORM_PRIORITY :5

涉及方法
  • getPriority() :返回線(xiàn)程優(yōu)先值

  • setPriority(int newPriority) : 改變線(xiàn)程的優(yōu)先級(jí)

說(shuō)明
  • 線(xiàn)程創(chuàng)建時(shí)繼承父線(xiàn)程的優(yōu)先級(jí)

  • 低優(yōu)先級(jí)只是獲得調(diào)度的概率低,并非一定是在高優(yōu)先級(jí)線(xiàn)程之后才被調(diào)用

線(xiàn)程分類(lèi)
  • Java中的線(xiàn)程分為兩類(lèi):一種是 守護(hù)線(xiàn)程秋柄,一種是 用戶(hù)線(xiàn)程

  • 守護(hù)線(xiàn)程是用來(lái)服務(wù)用戶(hù)線(xiàn)程的获枝,通過(guò)在start()方法前調(diào)用 thread.setDaemon(true)可以把一個(gè)用戶(hù)線(xiàn)程變成一個(gè)守護(hù)線(xiàn)程

  • Java垃圾回收就是一個(gè)典型的守護(hù)線(xiàn)程

  • 它們?cè)趲缀趺總€(gè)方面都是相同的,唯一的區(qū)別是判斷JVM何時(shí)離開(kāi)

  • 若JVM中都是守護(hù)線(xiàn)程骇笔,當(dāng)前JVM將退出

線(xiàn)程的生命周期
概述

JDK 中用Thread.State 類(lèi)定義了 線(xiàn)程的幾種狀態(tài)

  • 新建: 當(dāng)一個(gè)Thread類(lèi)或其子類(lèi)的對(duì)象被聲明并創(chuàng)建時(shí)省店,新生的線(xiàn)程對(duì)象處于新建 狀態(tài)

  • 就緒:處于新建狀態(tài)的線(xiàn)程被start()后,將進(jìn)入線(xiàn)程隊(duì)列等待CPU時(shí)間片蜘拉,此時(shí)它已 具備了運(yùn)行的條件萨西,只是沒(méi)分配到CPU資源

  • 運(yùn)行:當(dāng)就緒的線(xiàn)程被調(diào)度并獲得CPU資源時(shí),便進(jìn)入運(yùn)行狀態(tài), run()方法定義了線(xiàn)程的操作和功能

  • 阻塞:在某種特殊情況下旭旭,被人為掛起或執(zhí)行輸入輸出操作時(shí)谎脯,讓出 CPU 并臨時(shí)中止自己的執(zhí)行,進(jìn)入阻塞狀態(tài)

  • 死亡:線(xiàn)程完成了它的全部工作或線(xiàn)程被提前強(qiáng)制性地中止或出現(xiàn)異常導(dǎo)致結(jié)束

看圖
線(xiàn)程生命周期.png
線(xiàn)程狀態(tài)轉(zhuǎn)換.png
線(xiàn)程的同步
出現(xiàn)的安全問(wèn)題
  • 當(dāng)多條語(yǔ)句在操作同一個(gè)線(xiàn)程共享數(shù)據(jù)時(shí),一個(gè)線(xiàn)程對(duì)多條語(yǔ)句只執(zhí)行了一部分,還沒(méi)有執(zhí)行完吉挣,另一個(gè)線(xiàn)程參與進(jìn)來(lái)執(zhí)行。導(dǎo)致共享數(shù)據(jù)的錯(cuò)誤

  • 解決方案:對(duì)多條操作共享數(shù)據(jù)的語(yǔ)句废麻,只能讓一個(gè)線(xiàn)程都執(zhí)行完,在執(zhí)行過(guò)程中模庐,其他線(xiàn)程不可以參與執(zhí)行

同步機(jī)制 Synchronized
  • Java 對(duì)于多線(xiàn)程的安全問(wèn)題提供了專(zhuān)業(yè)的解決 方式 : 同步機(jī)制

  • 用法:

//同步代碼塊 :
synchronized ( 對(duì)象){
        //  需要被同步的代碼烛愧;
}

// synchronized 還可以放在方法聲明中,表示整個(gè)方法為同步方法
public synchronized void show (String name){
    ….
}
Synchronized鎖

在《Thinking in Java》中掂碱,是這么說(shuō)的:對(duì)于并發(fā)工作怜姿,你需要某種方式來(lái)防
止兩個(gè)任務(wù)訪(fǎng)問(wèn)相同的資源(其實(shí)就是共享資源競(jìng)爭(zhēng))。 防止這種沖突的方法
就是當(dāng)資源被一個(gè)任務(wù)使用時(shí)疼燥,在其上加鎖沧卢。第一個(gè)訪(fǎng)問(wèn)某項(xiàng)資源的任務(wù)必須
鎖定這項(xiàng)資源,使其他任務(wù)在其被解鎖之前醉者,就無(wú)法訪(fǎng)問(wèn)它了但狭,而在其被解鎖
之時(shí)披诗,另一個(gè)任務(wù)就可以鎖定并使用它了

  • 哪些操作會(huì)釋放鎖?

    • 1.當(dāng)前線(xiàn)程的同步方法立磁、同步代碼塊執(zhí)行結(jié)束

    • 2.當(dāng)前線(xiàn)程在同步代碼塊呈队、同步方法中遇到break、return終止了該代碼塊息罗、 該方法的繼續(xù)執(zhí)行

    • 3.當(dāng)前線(xiàn)程在同步代碼塊掂咒、同步方法中出現(xiàn)了未處理的Error或Exception,導(dǎo)致異常結(jié)束

    • 4.當(dāng)前線(xiàn)程在同步代碼塊迈喉、同步方法中執(zhí)行了線(xiàn)程對(duì)象的wait()方法,當(dāng)前線(xiàn)程暫停温圆,并釋放鎖

  • 哪些操作不會(huì)釋放鎖挨摸?

    • 1.線(xiàn)程執(zhí)行同步代碼塊或同步方法時(shí),程序調(diào)用Thread.sleep()岁歉、 Thread. Yield()方法暫停當(dāng)前線(xiàn)程的執(zhí)行

    • 2.線(xiàn)程執(zhí)行同步代碼塊時(shí)得运,其他線(xiàn)程調(diào)用了該線(xiàn)程的suspend()方法將該線(xiàn)程掛起,該線(xiàn)程不會(huì)釋放鎖(同步監(jiān)視器)锅移,應(yīng)盡量避免使用suspend()和resume()來(lái)控制線(xiàn)程

死鎖
  • 含義:不同的線(xiàn)程分別占用對(duì)方需要的同步資源不放棄熔掺,都在等待對(duì)方放棄自己需要的同步資源,就形成了線(xiàn)程的死鎖
Lock(鎖)
  • 含義: 從JDK 5.0開(kāi)始非剃,Java提供了更強(qiáng)大的線(xiàn)程同步機(jī)制——通過(guò)顯式定義同步鎖對(duì)象來(lái)實(shí)現(xiàn)同步置逻。同步鎖使用Lock對(duì)象充當(dāng)
     java.util.concurrent.locks.Lock接口是控制多個(gè)線(xiàn)程對(duì)共享資源進(jìn)行訪(fǎng)問(wèn)的
     工具。鎖提供了對(duì)共享資源的獨(dú)占訪(fǎng)問(wèn)备绽,每次只能有一個(gè)線(xiàn)程對(duì)Lock對(duì)象
     加鎖券坞,線(xiàn)程開(kāi)始訪(fǎng)問(wèn)共享資源之前應(yīng)先獲得Lock對(duì)象
     ?
     ReentrantLock 類(lèi)實(shí)現(xiàn)了 Lock ,它擁有與 synchronized 相同的并發(fā)性和
     內(nèi)存語(yǔ)義肺素,在實(shí)現(xiàn)線(xiàn)程安全的控制中恨锚,比較常用的是ReentrantLock,可以
     顯式加鎖倍靡、釋放鎖
  • 代碼
    class A{
      private final ReentrantLock lock = new ReenTrantLock();
      public void m(){
      lock.lock();
        try{
        // 保證線(xiàn)程安全的代碼;
        }finally{
          lock.unlock();
        }
      }
     }
synchronized 與 Lock 的對(duì)比
  • 1.Lock是顯式鎖(手動(dòng)開(kāi)啟和關(guān)閉鎖猴伶,別忘記關(guān)閉鎖),synchronized是 隱式鎖塌西,出了作用域自動(dòng)釋放

  • 2.Lock只有代碼塊鎖他挎,synchronized有代碼塊鎖和方法鎖

  • 3.使用Lock鎖,JVM將花費(fèi)較少的時(shí)間來(lái)調(diào)度線(xiàn)程雨让,性能更好雇盖。并且具有 更好的擴(kuò)展性(提供更多的子類(lèi))

進(jìn)程的通信
wait() 與 notify() 和 notifyAll()
  • wait():令當(dāng)前線(xiàn)程掛起并放棄CPU、同步資源并等待栖忠,使別的線(xiàn)程可訪(fǎng)問(wèn)并修改共享資源崔挖,而當(dāng)前線(xiàn)程排隊(duì)等候其他線(xiàn)程調(diào)用notify()或notifyAll()方法喚醒贸街,喚醒后等待重新獲得對(duì)監(jiān)視器的所有權(quán)后才能繼續(xù)執(zhí)行

  • notify(): 喚醒正在排隊(duì)等待同步資源的線(xiàn)程中優(yōu)先級(jí)最高者結(jié)束等待

  • notifyAll ():?jiǎn)拘颜谂抨?duì)等待資源的所有線(xiàn)程結(jié)束等待

  • 說(shuō)明:這三個(gè)方法只有在synchronized方法或synchronized代碼塊中才能使用,否則會(huì)報(bào)java.lang.IllegalMonitorStateException異常

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末狸相,一起剝皮案震驚了整個(gè)濱河市薛匪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌脓鹃,老刑警劉巖逸尖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異瘸右,居然都是意外死亡娇跟,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)太颤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)苞俘,“玉大人,你說(shuō)我怎么就攤上這事龄章〕砸ィ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵做裙,是天一觀(guān)的道長(zhǎng)岗憋。 經(jīng)常有香客問(wèn)我,道長(zhǎng)锚贱,這世上最難降的妖魔是什么仔戈? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮惋鸥,結(jié)果婚禮上杂穷,老公的妹妹穿的比我還像新娘。我一直安慰自己卦绣,他們只是感情好耐量,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著滤港,像睡著了一般廊蜒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上溅漾,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天山叮,我揣著相機(jī)與錄音,去河邊找鬼添履。 笑死屁倔,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的暮胧。 我是一名探鬼主播锐借,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼问麸,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了钞翔?” 一聲冷哼從身側(cè)響起严卖,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎布轿,沒(méi)想到半個(gè)月后哮笆,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡汰扭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年稠肘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片萝毛。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡启具,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出珊泳,到底是詐尸還是另有隱情,我是刑警寧澤拷沸,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布色查,位于F島的核電站,受9級(jí)特大地震影響撞芍,放射性物質(zhì)發(fā)生泄漏秧了。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一序无、第九天 我趴在偏房一處隱蔽的房頂上張望验毡。 院中可真熱鬧,春花似錦帝嗡、人聲如沸晶通。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)狮辽。三九已至,卻和暖如春巢寡,著一層夾襖步出監(jiān)牢的瞬間喉脖,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工抑月, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留树叽,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓谦絮,卻偏偏與公主長(zhǎng)得像题诵,于是被迫代替她去往敵國(guó)和親洁仗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 本文主要講了java中多線(xiàn)程的使用方法仇轻、線(xiàn)程同步京痢、線(xiàn)程數(shù)據(jù)傳遞、線(xiàn)程狀態(tài)及相應(yīng)的一些線(xiàn)程函數(shù)用法篷店、概述等祭椰。 首先講...
    李欣陽(yáng)閱讀 2,454評(píng)論 1 15
  • Java多線(xiàn)程學(xué)習(xí) [-] 一擴(kuò)展javalangThread類(lèi) 二實(shí)現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 2,957評(píng)論 1 18
  • 林炳文Evankaka原創(chuàng)作品。轉(zhuǎn)載自http://blog.csdn.net/evankaka 本文主要講了ja...
    ccq_inori閱讀 654評(píng)論 0 4
  • 1.1 多線(xiàn)程介紹 學(xué)習(xí)多線(xiàn)程之前疲陕,我們先要了解幾個(gè)關(guān)于多線(xiàn)程有關(guān)的概念方淤。 進(jìn)程:進(jìn)程指正在運(yùn)行的程序。確切的來(lái)說(shuō)...
    Pecksniff1994閱讀 1,556評(píng)論 0 2
  • 一擴(kuò)展javalangThread類(lèi)二實(shí)現(xiàn)javalangRunnable接口三Thread和Runnable的區(qū)...
    和帥_db6a閱讀 487評(píng)論 0 1