国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

多線程的創(chuàng)建和啟動(dòng)

IT那活兒 / 775人閱讀
多線程的創(chuàng)建和啟動(dòng)

點(diǎn)擊上方“IT那活兒”公眾號(hào),關(guān)注后了解更多內(nèi)容,不管IT什么活兒,干就完了!!!



多線程的創(chuàng)建和啟動(dòng)

1. 多線程的實(shí)現(xiàn)原理

  • Java語(yǔ)言的JVM允許程序運(yùn)行多個(gè)線程,多線程可以通過Java中的java.lang.Thread類來體現(xiàn)。
  • Thread類的特性。
每個(gè)線程都是通過某個(gè)特定的Thread對(duì)象的run()方法來完成操作,經(jīng)常把run()方法的主體作為線程體。
通過Thread方法的start()方法來啟動(dòng)這個(gè)線程,而非直接調(diào)用run()。

2. 多線程的創(chuàng)建

2.1 繼承Thread類

  • 創(chuàng)建一個(gè)繼承于Thread類的子類;
  • 重寫Thread類的run()方法;
  • 創(chuàng)建Thread類的子類的對(duì)象;
  • 通過此對(duì)象調(diào)用start()來啟動(dòng)一個(gè)線程。
示例一--多線程執(zhí)行同一段代碼:
示例二--多線程執(zhí)行多段代碼:
示例三--創(chuàng)建Thread匿名子類:

2.2 實(shí)現(xiàn)Runnable接口

  • 創(chuàng)建一個(gè)實(shí)現(xiàn)Runnable接口的類;
  • 實(shí)現(xiàn)類去實(shí)現(xiàn)Runnable接口中的抽象方法:run();
  • 創(chuàng)建實(shí)現(xiàn)類的對(duì)象;
  • 將此對(duì)象作為參數(shù)傳到Thread類的構(gòu)造器中,創(chuàng)建Thread類的對(duì)象;
  • 通過Thread類的對(duì)象調(diào)用start()方法。
示例:

2.3 兩種創(chuàng)建方式比較

  • Java中只允許單進(jìn)程,以賣票程序TiketSales類來說,很有可能這個(gè)類本來就有父類,這樣一來就不可以繼承Thread類來完成多線程了,但是一個(gè)類可以實(shí)現(xiàn)多個(gè)接口,因此實(shí)現(xiàn)的方式?jīng)]有類的單繼承性的局限性,用實(shí)現(xiàn)Runnable接口的方式來完成多線程更加實(shí)用。
  • 實(shí)現(xiàn)Runnable接口的方式天然具有共享數(shù)據(jù)的特性(不用static變量)。
    因?yàn)槔^承Thread的實(shí)現(xiàn)方式,需要?jiǎng)?chuàng)建多個(gè)子類的對(duì)象來進(jìn)行多線程,如果子類中有變量A,而不使用static約束變量的話,每個(gè)子類的對(duì)象都會(huì)有自己獨(dú)立的變量A,只有static約束A后,子類的對(duì)象才共享變量A。
    而實(shí)現(xiàn)Runnable接口的方式,只需要?jiǎng)?chuàng)建一個(gè)實(shí)現(xiàn)類的對(duì)象,要將這個(gè)對(duì)象傳入Thread類并創(chuàng)建多個(gè)Thread類的對(duì)象來完成多線程,而這多個(gè)Thread類對(duì)象實(shí)際上就是調(diào)用一個(gè)實(shí)現(xiàn)類對(duì)象而已。實(shí)現(xiàn)的方式更適合來處理多個(gè)線程有共享數(shù)據(jù)的情況。
  • 聯(lián)系:Thread類中也實(shí)現(xiàn)了Runnable接口。
  • 相同點(diǎn):兩種方式都需要重寫run()方法,線程的執(zhí)行邏輯都在run()方法中。

2.4 通過實(shí)現(xiàn)Callable接口

與Runnable相比,Callable功能更加強(qiáng)大:
  • 相比run()方法,可以有返回值;

  • 方法可以拋出異常;
  • 支持泛型的返回值;
  • 需要借助FutureTask類,比如獲取返回結(jié)果。
示例:

2.5 通過線程池創(chuàng)建

1)背景
經(jīng)常創(chuàng)建和銷毀、使用量特別大的資源,比如并發(fā)情況下的線程,對(duì)性能影響很大。
2)思路
提前創(chuàng)建好多個(gè)線程,放入線程池中,使用時(shí)直接獲取,使用完放回線程池中。可以避免頻繁的創(chuàng)建銷毀,實(shí)現(xiàn)重復(fù)利用。

3)優(yōu)點(diǎn)

  • 提高響應(yīng)速度(減少了創(chuàng)建新線程的時(shí)間);
  • 降低資源消耗(重復(fù)利用線程池中線程,不需要每次都創(chuàng)建);
  • 便于管理。
示例:



Thread類的常用方法

  • start():啟動(dòng)當(dāng)前線程, 調(diào)用當(dāng)前線程的run()方法;
  • run() : 通常需要重寫Thread類中的此方法, 將創(chuàng)建的線程要執(zhí)行的操作聲明在此方法中;
  • currentThread() : 靜態(tài)方法, 返回當(dāng)前代碼執(zhí)行的線程;
  • getName() : 獲取當(dāng)前線程的名字;
  • setName() : 設(shè)置當(dāng)前線程的名字;
  • yield() : 釋放當(dāng)前CPU的執(zhí)行權(quán);
  • join() : 在線程a中調(diào)用線程b的join(), 此時(shí)線程a進(jìn)入阻塞狀態(tài), 知道線程b完全執(zhí)行完以后, 線程a才結(jié)束阻塞狀態(tài);
  • stop() : 已過時(shí). 當(dāng)執(zhí)行此方法時(shí),強(qiáng)制結(jié)束當(dāng)前線程;
  • sleep(long militime) : 讓線程睡眠指定的毫秒數(shù),在指定時(shí)間內(nèi),線程是阻塞狀態(tài);
  • isAlive() :判斷當(dāng)前線程是否存活。



線程的調(diào)度

1. CPU的調(diào)度策略

  • 時(shí)間片:cpu正常情況下的調(diào)度策略。即CPU分配給各個(gè)程序的時(shí)間,每個(gè)線程被分配一個(gè)時(shí)間段,稱作它的時(shí)間片,即該進(jìn)程允許運(yùn)行的時(shí)間,使各個(gè)程序從表面上看是同時(shí)進(jìn)行的。

    如果在時(shí)間片結(jié)束時(shí)進(jìn)程還在運(yùn)行,則CPU將被剝奪并分配給另一個(gè)進(jìn)程。如果進(jìn)程在時(shí)間片結(jié)束前阻塞或結(jié)束,則CPU當(dāng)即進(jìn)行切換。而不會(huì)造成CPU資源浪費(fèi)。

    在宏觀上:我們可以同時(shí)打開多個(gè)應(yīng)用程序,每個(gè)程序并行不悖,同時(shí)運(yùn)行。

    在微觀上:由于只有一個(gè)CPU,一次只能處理程序要求的一部分,如何處理公平,一種方法就是引入時(shí)間片,每個(gè)程序輪流執(zhí)行。

  • 搶占式:高優(yōu)先級(jí)的線程搶占cpu。

2. Java的調(diào)度算法

  • 同優(yōu)先級(jí)線程組成先進(jìn)先出隊(duì)列(先到先服務(wù)),使用時(shí)間片策略。
  • 堆高優(yōu)先級(jí),使用優(yōu)先調(diào)度的搶占式策略。

1)線程的優(yōu)先級(jí)等級(jí)(一共有10檔)

  • MAX_PRIORITY:10;

  • MIN_PRIORITY:1;

  • NORM_PRIORITY:5 (默認(rèn)優(yōu)先級(jí))。

2)獲取和設(shè)置當(dāng)前線程的優(yōu)先級(jí)

  • getPriority()獲取;
  • setPriority(int p)設(shè)置。
說明:高優(yōu)先級(jí)的線程要搶占低優(yōu)先級(jí)線程cpu的執(zhí)行權(quán)。但是只是從概率上講,高優(yōu)先級(jí)的線程高概率的情況下被執(zhí)行。并不意味著只有高優(yōu)先級(jí)的線程執(zhí)行完成以后,低優(yōu)先級(jí)的線程才執(zhí)行。



線程的生命周期

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

  • 新建:當(dāng)一個(gè)Thread類或其子類的對(duì)象被聲明并創(chuàng)建時(shí),新的線程對(duì)象處于新建狀態(tài)。
  • 就緒:處于新建狀態(tài)的線程被start()后,將進(jìn)入線程隊(duì)列等待CPU時(shí)間片,此時(shí)它已具備了運(yùn)行的條件,只是沒分配到CPU資源。
  • 運(yùn)行當(dāng)就緒的線程被調(diào)度并獲得CPU資源時(shí),便進(jìn)入運(yùn)行狀態(tài),run()方法定義了線程的操作和功能。
  • 阻塞:在某種特殊情況下,被認(rèn)為掛起或執(zhí)行輸入輸出操作時(shí),讓出CPU并臨時(shí)中止自己的執(zhí)行,進(jìn)入阻塞狀態(tài)。
  • 死亡:線程完成了它的全部工作或線程被提前強(qiáng)制性的中止或出現(xiàn)異常倒置導(dǎo)致結(jié)束。
2. 線程的生命周期流程圖



線程的同步

1. 多線程的安全性問題解析

1.1 線程的安全問題

  • 多個(gè)線程執(zhí)行的不確定性引起執(zhí)行結(jié)果的不穩(wěn)定性;
  • 多個(gè)線程對(duì)賬本的共享, 會(huì)造成操作的不完整性, 會(huì)破壞數(shù)據(jù);
  • 多個(gè)線程訪問共享的數(shù)據(jù)時(shí)可能存在安全性問題。
示例:
1.2 輸出結(jié)果
1.3 錯(cuò)誤分析
當(dāng)票數(shù)為1的時(shí)候,三個(gè)線程中有線程被阻塞沒有執(zhí)行票數(shù)-1的操作,這是其它線程就會(huì)通過if語(yǔ)句的判斷,這樣一來就會(huì)造成多賣了一張票,出現(xiàn)錯(cuò)票的情況。
極端情況為,當(dāng)票數(shù)為1時(shí),三個(gè)線程同時(shí)判斷通過,進(jìn)入阻塞,然后多執(zhí)行兩側(cè)賣票操作。
1.4 重票分析
如果t1在輸出票號(hào)22和票數(shù)-1的操作之間被阻塞,這就導(dǎo)致這時(shí)候t1賣出了22號(hào)票,但是總票數(shù)沒有減少。在t1被阻塞期間,如果t2運(yùn)行到輸出票號(hào)時(shí),那么t2也會(huì)輸出和t1相同的票號(hào)22。
通過以上兩種情況可以看出,線程的安全性問題時(shí)因?yàn)槎鄠€(gè)線程正在執(zhí)行代碼的過程中,并且尚未完成的時(shí)候,其他線程參與進(jìn)來執(zhí)行代碼所導(dǎo)致的。

2. 多線程安全性問題解決

2.1 原理
當(dāng)一個(gè)線程在操作共享數(shù)據(jù)的時(shí)候,其他線程不能參與進(jìn)來。知道這個(gè)線程操作完共享數(shù)據(jù)的時(shí)候,其他線程才可以操作。即使當(dāng)這個(gè)線程操作共享數(shù)據(jù)的時(shí)候發(fā)生了阻塞,依舊無法改變這種情況。
在Java中,我們通過同步機(jī)制,來解決線程的安全問題。
2.2 解決方式
1)同步代碼塊

synchronized(同步監(jiān)視器){需要被同步的代碼塊}

  • 優(yōu)點(diǎn):同步的方式,解決了線程安全的問題。
  • 缺點(diǎn):操作同步代碼時(shí),只能有一個(gè)線程參與,與其他線程等待。相當(dāng)于是一個(gè)單線程的過程,效率低。
2)同步方法
將所要同步的代碼放到一個(gè)方法中,將方法聲明為synchronized同步方法。之后可以在run()方法中調(diào)用同步方法。

要點(diǎn):

  • 同步方法仍然涉及到同步監(jiān)視器,只是不需要我們顯示的聲明。
  • 非靜態(tài)的同步方法,同步監(jiān)視器是:this。
  • 靜態(tài)的同步方法,同步監(jiān)視器是:當(dāng)前類本身。
3)Lock鎖-JDK 5.0的新特性
JDK5.0之后,可以通過實(shí)例化ReentrantLock對(duì)象,在所需要同步的語(yǔ)句前,調(diào)用ReentrantLock對(duì)象的lock()方法,實(shí)現(xiàn)同步鎖,在同步語(yǔ)句結(jié)束時(shí),調(diào)用unlock()方法結(jié)束同步鎖。
建議使用順序:Lock->同步代碼塊(已經(jīng)進(jìn)入了方法體,分配了相應(yīng)的資源)->同步方法(在方法體之外)。

2.3 線程同步的死鎖問題

1)原理

  • 不同的線程分別占用對(duì)方需要的同步資源不放棄,都在等待對(duì)方放棄自己需要的同步資源,就形成了死鎖。
  • 出現(xiàn)死鎖后,并不會(huì)出現(xiàn)異常,不會(huì)出現(xiàn)提示,只是所有的線程都處于阻塞狀態(tài),無法繼續(xù)。
  • 使用同步時(shí)應(yīng)避免出現(xiàn)死鎖。
2)Java中思索最簡(jiǎn)單的情況
一個(gè)線程T1持有鎖L1并且申請(qǐng)獲得鎖L2,而另一個(gè)線程T2持有鎖L2并且申請(qǐng)獲得鎖L1,因?yàn)槟J(rèn)的鎖申請(qǐng)操作都是阻塞的,所以線程T1和T2永遠(yuǎn)被阻塞了。導(dǎo)致了死鎖。這是最容易理解也是最簡(jiǎn)單的死鎖的形式。但是實(shí)際環(huán)境中的死鎖往往比這個(gè)復(fù)雜的多。可能會(huì)有多個(gè)線程形成了一個(gè)死鎖的環(huán)路,比如:線程T1持有鎖L1并且申請(qǐng)獲得鎖L2,而線程T2持有鎖L2并且申請(qǐng)獲得鎖L3,而線程T3持有鎖L3并且申請(qǐng)獲得鎖L1,這樣導(dǎo)致了一個(gè)鎖依賴的環(huán)路:T1依賴T2的鎖L2,T2依賴T3的鎖L3,而T3依賴T1的鎖L1。從而導(dǎo)致了死鎖。
從上面的例子分析出原因:
線程在獲得一個(gè)鎖L1的情況下再去申請(qǐng)另外一個(gè)鎖L2,也就是鎖L1想要包含了鎖L2,也就是說在獲得了鎖L1,并且沒有釋放鎖L1的情況下,又去申請(qǐng)獲得鎖L2,這個(gè)是產(chǎn)生死鎖的最根本原因。另一個(gè)原因是默認(rèn)的鎖申請(qǐng)操作是阻塞的。

3)死鎖的解決辦法

  • 專門的算法、原則。
  • 盡量減少同步資源的定義。
  • 盡量避免嵌套同步。
示例:



線程通信

很多情況下,盡管我們創(chuàng)建了多個(gè)線程,也會(huì)出現(xiàn)幾乎一個(gè)線程執(zhí)行完所有操作的時(shí)候,這時(shí)候我們就需要讓線程間相互交流。

1. 原理
當(dāng)一個(gè)線程執(zhí)行完成其所應(yīng)該執(zhí)行的代碼后,手動(dòng)讓這個(gè)線程進(jìn)入阻塞狀態(tài),這樣一來,接下來的操作只能由其他線程來操作。
當(dāng)其他線程執(zhí)行的開始階段,再手動(dòng)讓已經(jīng)阻塞的線程停止阻塞,進(jìn)入就緒狀態(tài),雖說這時(shí)候阻塞的線程停止了阻塞,但是由于現(xiàn)在正在運(yùn)行的線程拿著同步鎖,所以停止阻塞的線程也無法立馬執(zhí)行。
如此操作就可以完成線程間的通信。

2. 所用到的方法

  • wait():一旦執(zhí)行此方法,當(dāng)前線程就會(huì)進(jìn)入阻塞,一旦執(zhí)行wait()會(huì)釋放同步監(jiān)視器。
  • notify():一旦執(zhí)行此方法,將會(huì)喚醒被wait的一個(gè)線程。如果有多個(gè)線程被wait,就喚醒優(yōu)先度最高的。
  • notifyAll() :一旦執(zhí)行此方法,就會(huì)喚醒所有被wait的線程。
3. 說明
這三個(gè)方法必須在同步代碼塊或同步方法中使用。
三個(gè)方法的調(diào)用者必須是同步代碼塊或同步方法中的同步監(jiān)視器。 
這三個(gè)方法并不時(shí)定義在Thread類中的,而是定義在Object類當(dāng)中的。因?yàn)樗械膶?duì)象都可以作為同步監(jiān)視器,而這三個(gè)方法需要由同步監(jiān)視器調(diào)用,所以任何一個(gè)類都要滿足,那么只能寫在Object類中。
4. sleep()和wait()的異同
相同點(diǎn):兩個(gè)方法一旦執(zhí)行,都可以讓線程進(jìn)入阻塞狀態(tài)。

不同點(diǎn):

  • 兩個(gè)方法聲明的位置不同:Thread類中聲明sleep(),Object類中聲明wait()。
  • 調(diào)用要求不同:sleep()可以在任何需要的場(chǎng)景下調(diào)用。wait()必須在同步代碼塊中調(diào)用。
  • 關(guān)于是否釋放同步監(jiān)視器:如果兩個(gè)方法都使用在同步代碼塊呵呵同步方法中,sleep不會(huì)釋放鎖,wait會(huì)釋放鎖。
示例:


END




本文作者:趙畢皓(上海新炬王翦團(tuán)隊(duì))

本文來源:“IT那活兒”公眾號(hào)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/129430.html

相關(guān)文章

  • 什么是Java線程

    摘要:是不能直接調(diào)用系統(tǒng)功能的,所以,我們沒有辦法直接實(shí)現(xiàn)多線程程序。通過查看,我們知道了有種方式實(shí)現(xiàn)多線程程序。使用的是搶占式調(diào)度模型演示如何設(shè)置和獲取線程優(yōu)先級(jí)返回線程對(duì)象的優(yōu)先級(jí)更改線程的優(yōu)先級(jí)線程默認(rèn)優(yōu)先級(jí)是。線程優(yōu)先級(jí)的范圍是。 第五階段 多線程 前言: 一個(gè)場(chǎng)景:周末,帶著并不存在的女票去看電影,無論是現(xiàn)場(chǎng)買票也好,又或是手機(jī)買票也好,上一秒還有位置,遲鈍了一下以后,就顯示該座位...

    高璐 評(píng)論0 收藏0
  • Java 線程編程基礎(chǔ)——Thread 類

    摘要:程序執(zhí)行時(shí),至少會(huì)有一個(gè)線程在運(yùn)行,這個(gè)運(yùn)行的線程被稱為主線程。程序的終止是指除守護(hù)線程以外的線程全部終止。多線程程序由多個(gè)線程組成的程序稱為多線程程序。線程休眠期間可以被中斷,中斷將會(huì)拋出異常。 線程 我們?cè)陂喿x程序時(shí),表面看來是在跟蹤程序的處理流程,實(shí)際上跟蹤的是線程的執(zhí)行。 單線程程序 在單線程程序中,在某個(gè)時(shí)間點(diǎn)執(zhí)行的處理只有一個(gè)。 Java 程序執(zhí)行時(shí),至少會(huì)有一個(gè)線程在運(yùn)行...

    zhoutk 評(píng)論0 收藏0
  • Java 線程

    摘要:當(dāng)一個(gè)程序運(yùn)行時(shí),內(nèi)部可能包含了多個(gè)順序執(zhí)行流,每個(gè)順序執(zhí)行流就是一個(gè)線程所有運(yùn)行中的任務(wù)通常對(duì)應(yīng)一個(gè)進(jìn)程。線程也被稱作輕量級(jí)進(jìn)程,線程是進(jìn)程的執(zhí)行單元。在線程的生命周期中,它要經(jīng)過新 線程概述 線程和進(jìn)程 幾乎所有的操作系統(tǒng)都支持同時(shí)運(yùn)行多個(gè)任務(wù),一個(gè)任務(wù)通常就是一個(gè)程序,每個(gè)運(yùn)行中的程序就是一個(gè)進(jìn)程。當(dāng)一個(gè)程序運(yùn)行時(shí),內(nèi)部可能包含了多個(gè)順序執(zhí)行流,每個(gè)順序執(zhí)行流就是一個(gè)線程 所有運(yùn)...

    zorro 評(píng)論0 收藏0
  • 大話javascript 4期:事件循環(huán)(1)

    摘要:腳本執(zhí)行,事件處理等。引擎線程,也稱為內(nèi)核,負(fù)責(zé)處理腳本程序,例如引擎。事件觸發(fā)線程,用來控制事件循環(huán)可以理解為,引擎線程自己都忙不過來,需要瀏覽器另開線程協(xié)助。異步請(qǐng)求線程,也就是發(fā)出請(qǐng)求后,接收響應(yīng)檢測(cè)狀態(tài)變更等都是這個(gè)線程管理的。 一、進(jìn)程與線程 現(xiàn)代操作系統(tǒng)比如Mac OS X,UNIX,Linux,Windows等,都是支持多任務(wù)的操作系統(tǒng)。 什么叫多任務(wù)呢?簡(jiǎn)單地說,就是操...

    codergarden 評(píng)論0 收藏0
  • java 線程

    摘要:總結(jié)創(chuàng)建線程,方法運(yùn)行線程。創(chuàng)建線程使用繼承類實(shí)現(xiàn)創(chuàng)建線程文檔該類必須重寫方法。為新線程的入口點(diǎn)。中斷線程它表示一個(gè)線程被中斷,會(huì)拋出錯(cuò)誤。 java多線程 關(guān)于內(nèi)存 每個(gè)線程會(huì)有自己的線程棧,即,變量不能共享,只能傳值拷貝每個(gè)線程new出的對(duì)象全都保存在堆中,全部共享 線程的生命周期 線程具有5種狀態(tài),即新建,就緒,運(yùn)行,阻塞,死亡。新建,當(dāng)new出來一個(gè)線程以后,jvm為其分配內(nèi)存...

    IamDLY 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<