多線程并發(fā)詳解

一蝶念、Java 線程實(shí)現(xiàn)/創(chuàng)建方式

注意:

? 新建的線程不會(huì)自動(dòng)開(kāi)始運(yùn)行劝贸,必須通過(guò)start( )方法啟動(dòng)

? 不能直接調(diào)用run()來(lái)啟動(dòng)線程,這樣run()將作為一個(gè)普通方法立即執(zhí)行挚躯,執(zhí)行完畢前其他線程無(wú)法并發(fā)執(zhí)行

? Java程序啟動(dòng)時(shí)锤岸,會(huì)立刻創(chuàng)建主線程集漾,main就是在這個(gè)線程上運(yùn)行。當(dāng)不再產(chǎn)生新線程時(shí)砸脊,程序是單線程的

1.1 繼承Thread 類

Thread 類本質(zhì)上是實(shí)現(xiàn)了 Runnable 接口的一個(gè)實(shí)例具篇,代表一個(gè)線程的實(shí)例。啟動(dòng)線程的唯一方法就是通過(guò) Thread 類的 start()實(shí)例方法凌埂。start()方法是一個(gè) native 方法驱显,它將啟動(dòng)一個(gè)新線程,并執(zhí)行 run()方法瞳抓。

? 優(yōu)勢(shì):編寫簡(jiǎn)單

? 劣勢(shì):無(wú)法繼承其它父類

1.1.1 ****創(chuàng)建:繼承Thread+重寫run

  1.1.2 啟動(dòng):創(chuàng)建子類對(duì)象+調(diào)用start

public class StartThread extends Thread{

//線程入口點(diǎn)

@Override

public void run() {

for(int i=0;i<10;i++) {

System.out.println("listen music");

}

}

public static void main(String[] args) {

//創(chuàng)建子類對(duì)象

StartThread st=new StartThread();

//調(diào)用start方法

st.start();//開(kāi)啟新線程交于cpu決定執(zhí)行順序

for(int i=0;i<10;i++) {

System.out.println("coding");

}

}

}

1.2 實(shí)現(xiàn)runnable接口

如果自己的類已經(jīng) extends 另一個(gè)類埃疫,就無(wú)法直接 extends Thread,此時(shí)挨下,可以實(shí)現(xiàn)一個(gè)Runnable 接口熔恢。

? 優(yōu)勢(shì):可以繼承其它類脐湾,多線程可共享同一個(gè)Runnable對(duì)象

? 劣勢(shì):編程方式稍微復(fù)雜臭笆,如果需要訪問(wèn)當(dāng)前線程,需要調(diào)用Thread.currentThread()方法

1.2.1 創(chuàng)建:實(shí)現(xiàn)runnable接口+重寫run

   1.2.2 啟動(dòng):創(chuàng)建實(shí)現(xiàn)類對(duì)象+Thread類對(duì)象+調(diào)用start

public class StartRun implements Runnable{

//線程入口點(diǎn)

@Override

public void run() {

for(int i=0;i<10;i++) {

System.out.println("listen music");

}

}

public static void main(String[] args) {

//創(chuàng)建實(shí)現(xiàn)類對(duì)象

StartRun st=``new` `StartRun();

//創(chuàng)建代理類對(duì)象<br>         
 //啟動(dòng) MyThread秤掌,需要首先實(shí)例化一個(gè) Thread愁铺,并傳入自己的 MyThread 實(shí)例:`
Thread t=``new` `Thread(st);

//事實(shí)上,當(dāng)傳入一個(gè) Runnable target 參數(shù)給 Thread 后闻鉴,Thread 的 run()方法就會(huì)調(diào)用target.run()

//調(diào)用start方法

t.start();//開(kāi)啟新線程交于cpu決定執(zhí)行順序`

//匿名法

//      new Thread(new StartRun()).start();

for(int i=0;i<10;i++) {

System.out.println("coding");

}

}

}

1.3 實(shí)現(xiàn)Callable接口

有返回值的任務(wù)必須實(shí)現(xiàn) Callable 接口茵乱,類似的,無(wú)返回值的任務(wù)必須 Runnable 接口孟岛。執(zhí)行Callable 任務(wù)后瓶竭,可以獲取一個(gè) Future 的對(duì)象,在該對(duì)象上調(diào)用 get 就可以獲取到 Callable 任務(wù)返回的 Object 了渠羞,再結(jié)合線程池接口 ExecutorService 就可以實(shí)現(xiàn)傳說(shuō)中有返回結(jié)果的多線程了斤贰。

? 與實(shí)行Runnable相比, Callable功能更強(qiáng)大些

? 方法不同

? 可以有返回值次询,支持泛型的返回值

? 可以拋出異常

? 需要借助FutureTask荧恍,比如獲取返回結(jié)果

Future接口

? 可以對(duì)具體Runnable、Callable任務(wù)的執(zhí)行結(jié)果進(jìn)行取消屯吊、查詢是否完成送巡、獲取結(jié)果等。

? FutrueTask是Futrue接口的唯一的實(shí)現(xiàn)類

? FutureTask 同時(shí)實(shí)現(xiàn)了Runnable, Future接口盒卸。它既可以作為Runnable被線程執(zhí)行骗爆,又可以作為Future得到Callable的返回值

//創(chuàng)建一個(gè)線程池

ExecutorService pool = Executors.newFixedThreadPool(taskSize);

// 創(chuàng)建多個(gè)有返回值的任務(wù)`

List<Future> list = new ArrayList<Future>();

for (int i = 0; i < taskSize; i++) {

Callable c = ``new` `MyCallable(i +" ");

// 執(zhí)行任務(wù)并獲取 Future 對(duì)象

Future f = pool.submit(c);

list.add(f);

}

// 關(guān)閉線程池

pool.shutdown();

// 獲取所有并發(fā)任務(wù)的運(yùn)行結(jié)果`

for (Future f : list) {

// 從 Future 對(duì)象上獲取任務(wù)的返回值,并輸出到控制臺(tái)

System.out.println(``"res:"` `+ f.get().toString());

}

1.4 基于線程池的方式

線程和數(shù)據(jù)庫(kù)連接這些資源都是非常寶貴的資源蔽介。那么每次需要的時(shí)候創(chuàng)建摘投,不需要的時(shí)候銷毀糟需,是非常浪費(fèi)資源的。那么我們就可以使用緩存的策略谷朝,也就是使用線程池洲押。

// 創(chuàng)建線程池

ExecutorService threadPool = Executors.newFixedThreadPool(10);

while(true) {

threadPool.execute(new Runnable() { // 提交多個(gè)線程任務(wù),并執(zhí)行

@Override

public void run() {

System.out.println(Thread.currentThread().getName() + " is running ..");

try {

Thread.sleep(3000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

});

}

}               `

二圆凰、四種線程池

Java 里面線程池的頂級(jí)接口是 Executor杈帐,但是嚴(yán)格意義上講 Executor 并不是一個(gè)線程池,而只是一個(gè)執(zhí)行線程的工具专钉。真正的線程池接口是 ExecutorService挑童。

image

2.1 newCachedThreadPool

創(chuàng)建一個(gè)可根據(jù)需要?jiǎng)?chuàng)建新線程的線程池,但是在以前構(gòu)造的線程可用時(shí)將重用它們跃须。對(duì)于執(zhí)行很多短期異步任務(wù)的程序而言站叼,這些線程池通常可提高程序性能菇民。調(diào)用 execute 將重用以前構(gòu)造的線程(如果線程可用)尽楔。如果現(xiàn)有線程沒(méi)有可用的,則創(chuàng)建一個(gè)新線程并添加到池中第练。終止并從緩存中移除那些已有 60 秒鐘未被使用的線程阔馋。因此,長(zhǎng)時(shí)間保持空閑的線程池不會(huì)使用任何資源娇掏。

2.2 newFixedThreadPool

創(chuàng)建一個(gè)可重用固定線程數(shù)的線程池呕寝,以共享的無(wú)界隊(duì)列方式來(lái)運(yùn)行這些線程。在任意點(diǎn)婴梧,在大多數(shù) Threads 線程會(huì)處于處理任務(wù)的活動(dòng)狀態(tài)下梢。如果在所有線程處于活動(dòng)狀態(tài)時(shí)提交附加任務(wù),則在有可用線程之前塞蹭,附加任務(wù)將在隊(duì)列中等待孽江。如果在關(guān)閉前的執(zhí)行期間由于失敗而導(dǎo)致任何線程終止,那么一個(gè)新線程將代替它執(zhí)行后續(xù)的任務(wù)(如果需要)浮还。在某個(gè)線程被顯式地關(guān)閉之前竟坛,池中的線程將一直存在

2.3 newScheduledThreadPool

創(chuàng)建一個(gè)線程池钧舌,它可安排在給定延遲后運(yùn)行命令或者定期地執(zhí)行担汤。

ScheduledExecutorService scheduledThreadPool= Executors.newScheduledThreadPool(3);

scheduledThreadPool.schedule(newRunnable(){

@Override

public void run() {

System.out.println("延遲三秒");

}

}, 3, TimeUnit.SECONDS);

scheduledThreadPool.scheduleAtFixedRate(newRunnable(){

@Override

public void run() {

System.out.println延遲 1 秒后每三秒執(zhí)行一次");

},1,3,TimeUnit.SECONDS);

2.4 newSingleThreadExecutor

Executors.newSingleThreadExecutor()返回一個(gè)線程池(這個(gè)線程池只有一個(gè)線程),這個(gè)線程池可以在線程死后(或發(fā)生異常時(shí))重新啟動(dòng)一個(gè)線程來(lái)替代原來(lái)的線程繼續(xù)執(zhí)行下去!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末洼冻,一起剝皮案震驚了整個(gè)濱河市崭歧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌撞牢,老刑警劉巖率碾,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叔营,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡所宰,警方通過(guò)查閱死者的電腦和手機(jī)绒尊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)仔粥,“玉大人婴谱,你說(shuō)我怎么就攤上這事∏” “怎么了谭羔?”我有些...
    開(kāi)封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)麦向。 經(jīng)常有香客問(wèn)我瘟裸,道長(zhǎng),這世上最難降的妖魔是什么诵竭? 我笑而不...
    開(kāi)封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任话告,我火速辦了婚禮,結(jié)果婚禮上秀撇,老公的妹妹穿的比我還像新娘超棺。我一直安慰自己,他們只是感情好呵燕,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著件相,像睡著了一般再扭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上夜矗,一...
    開(kāi)封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天泛范,我揣著相機(jī)與錄音,去河邊找鬼紊撕。 笑死罢荡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的对扶。 我是一名探鬼主播区赵,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼浪南!你這毒婦竟也來(lái)了笼才?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤络凿,失蹤者是張志新(化名)和其女友劉穎骡送,沒(méi)想到半個(gè)月后昂羡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡摔踱,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年虐先,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片派敷。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡赴穗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出膀息,到底是詐尸還是另有隱情般眉,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布潜支,位于F島的核電站甸赃,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏冗酿。R本人自食惡果不足惜埠对,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望裁替。 院中可真熱鬧项玛,春花似錦、人聲如沸弱判。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)昌腰。三九已至开伏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間遭商,已是汗流浹背固灵。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留劫流,地道東北人巫玻。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像祠汇,于是被迫代替她去往敵國(guó)和親仍秤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355