您好,登錄后才能下訂單哦!
.一、概述:
從c開(kāi)始,任何一門(mén)語(yǔ)言的默認(rèn)執(zhí)行順序都是按照一條路走到黑的方式。
但是,當(dāng)我們需要同時(shí)進(jìn)行多項(xiàng)任務(wù)的時(shí)候該怎么辦呢?這時(shí)我們可以將一個(gè)任務(wù)拆分成多個(gè)小任務(wù)同時(shí)處理(深層一點(diǎn)講,就是雖然我單線程也能夠做的到,但是cpu沒(méi)有最高效率的利用,時(shí)間也沒(méi)有高效的利用)。
所以:多線程解決的是并發(fā)的問(wèn)題,目的是使任務(wù)執(zhí)行效率更高,實(shí)現(xiàn)前提是“阻塞”。它們看上去時(shí)同時(shí)在執(zhí)行的,但實(shí)際上只是分時(shí)間片試用cpu而已。
二、java任務(wù):
作為一只Red_Ant,我才不關(guān)心Black_Ant搬過(guò)來(lái)的食物建筑的巢穴是怎么來(lái)的,因此java底層的多線程機(jī)制是如何執(zhí)行的,這里就交給Black_Ant了。
java任務(wù)就是:實(shí)現(xiàn)Runnable接口類定義一個(gè)類。
那就簡(jiǎn)單了,就是說(shuō)平常寫(xiě)的功能、方法、變量只要實(shí)現(xiàn)Runnable接口,把該任務(wù)實(shí)現(xiàn)的代碼寫(xiě)到run方法中或者run方法調(diào)用就OK了。
舉例:
package com.css.java.learning.action;
public class Task1 implements Runnable {
protected int countDown = 10;
public Task1(int countDown){
this.countDown = countDown;
}
public String mhtao(){
return "論10斤,紅心獼猴桃可以吃幾天?";
}
@Override
public void run() {
while(countDown-->0){
System.err.println(mhtao());
/**
* Java線程中的Thread.yield( )方法,譯為線程讓步,它能讓當(dāng)前線程由“運(yùn)行狀態(tài)”進(jìn)入到“就緒狀態(tài)”。
* 顧名思義,就是說(shuō)當(dāng)一個(gè)線程使用了這個(gè)方法之后,它就會(huì)把自己CPU執(zhí)行的時(shí)間讓掉。
* 然后,自己和其他線程一樣。依據(jù)cup的執(zhí)行概率來(lái)執(zhí)行自己或其他線程
* 用Red_Ant的話來(lái)講就是:大家依次排隊(duì)擠公交,輪到這貨了。
* 這貨沒(méi)有上車,而是講了一句話:“大家一塊兒擠啊,誰(shuí)上去算誰(shuí)的座位”。
* 于是輪流事件就變成了概率事件,個(gè)子大,有力氣的可能概率大一點(diǎn),后面的也有概率,不過(guò)小一點(diǎn)。
*/
Thread.yield();
}
}
}
定義了任務(wù),此時(shí)并不涉及多線程,所以,任務(wù)本身就是一個(gè)類,它的對(duì)象我們可以在任意地方調(diào)用。
三、java線程:
java的線程是用來(lái)驅(qū)動(dòng)任務(wù)執(zhí)行的,也就是說(shuō)你得把任務(wù)掛載到一個(gè)線程上,這樣該線程才能驅(qū)動(dòng)你定義的任務(wù)來(lái)執(zhí)行。
①定義:
線程Thread自身并不執(zhí)行任何操作,它只是用來(lái)被多線程機(jī)制調(diào)用,并驅(qū)動(dòng)賦予它的任務(wù)。
聲明線程并將任務(wù)附著到該線程上:
Thread t = new Thread(new Task1(5));
這樣,任務(wù)就附著給了線程,下面就是讓線程啟動(dòng),只需要如下的調(diào)用:
t.start();
至此,線程聲明ok。
②舉例:
package com.css.java.learning.action;
public class Thread1 {
public static void main(String[] args) {
Thread t = new Thread(new Task1(5));
t.start();
System.err.println("線程任務(wù)已被java調(diào)用!");
}
}
可以看出,java調(diào)用線程之后。立馬返回到了主程序上,然后再利用java的多線程機(jī)制,進(jìn)行任務(wù)執(zhí)行。
為了更深入的看清,java線程的本質(zhì)。
我這里在定義一個(gè)任務(wù),掛到線程上去。
package com.css.java.learning.action;
public class Task2 implements Runnable {
protected int countDown = 10;
public String mhtao(){
return "答:可以吃3天!";
}
@Override
public void run() {
while(countDown-->0){
System.err.println(mhtao());
Thread.yield();
}
}
}
線程調(diào)用:
package com.css.java.learning.action;
public class Thread1 {
public static void main(String[] args) {
Thread t = new Thread(new Task1(5));
t.start();
Thread t2 = new Thread(new Task2());
t2.start();
System.err.println("線程任務(wù)已被java調(diào)用!");
}
}
隨機(jī)性
運(yùn)行結(jié)果一:
運(yùn)行結(jié)果二:
好了,運(yùn)行結(jié)果都在這了。筆者就不多說(shuō)了。
四、java多線程管家:
這里,筆者科普一下Executor線程池框架!
我們通過(guò)上述方法,創(chuàng)建的線程。雖然稱之為線程,但他是沒(méi)人管的野線程。
調(diào)用new Thread()創(chuàng)建的線程缺乏管理,而且可以無(wú)限制創(chuàng)建,之間相互競(jìng)爭(zhēng),會(huì)導(dǎo)致過(guò)多占用系統(tǒng)資源導(dǎo)致系統(tǒng)癱瘓。 不利于擴(kuò)展,比如如定時(shí)執(zhí)行、定期執(zhí)行、線程中斷。
我們,得找東西管管它啊。Executor線程管家來(lái)嘍。
重用存在的線程,減少對(duì)象創(chuàng)建、消亡的開(kāi)銷,性能佳
可有效控制最大并發(fā)線程數(shù),提高系統(tǒng)資源的使用率,同時(shí)避免過(guò)多資源競(jìng)爭(zhēng),避免堵塞
提供定時(shí)執(zhí)行、定期執(zhí)行、單線程、并發(fā)數(shù)控制等功能。
其內(nèi)部使用了線程池機(jī)制,它在java.util.cocurrent 包下,通過(guò)該框架來(lái)控制線程的啟動(dòng)、執(zhí)行和關(guān)閉,可以簡(jiǎn)化并發(fā)編程的操作。因此,在Java 5之后,通過(guò)Executor來(lái)啟動(dòng)線程比使用Thread的start方法更好,除了更易管理,效率更好(用線程池實(shí)現(xiàn),節(jié)約開(kāi)銷)外,還有關(guān)鍵的一點(diǎn):有助于避免this逃逸問(wèn)題——如果我們?cè)跇?gòu)造器中啟動(dòng)一個(gè)線程,因?yàn)榱硪粋€(gè)任務(wù)可能會(huì)在構(gòu)造器結(jié)束之前開(kāi)始執(zhí)行,此時(shí)可能會(huì)訪問(wèn)到初始化了一半的對(duì)象用Executor在構(gòu)造器中。
Executor框架包括:線程池,Executor,Executors,ExecutorService,CompletionService,F(xiàn)uture,Callable等。
我們將在下一篇文章,講述java多線程管家:Executor!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。