Java多線程


線程是指程序在執(zhí)行過程中谓松,能過執(zhí)行程序代碼的一個(gè)執(zhí)行單元践剂。在Java中,線程有4種狀態(tài):運(yùn)行逊脯、就緒、掛起和結(jié)束军洼。
進(jìn)程是指一段正在執(zhí)行的程序巩螃。而線程有時(shí)被稱為輕量級(jí)進(jìn)程匕争,它是程序執(zhí)行的最小單元避乏,一個(gè)進(jìn)程可以擁有多個(gè)線程,各個(gè)線程之間共享程序的內(nèi)存空間(代碼段甘桑、數(shù)據(jù)段和堆空間)及一些進(jìn)程級(jí)的資源(如打開文件)拍皮,但是各個(gè)線程擁有自己的棧空間跑杭。


進(jìn)程和線程的關(guān)系.png

多線程的使用的好處:

  • 使用多線程可以減少程序的響應(yīng)時(shí)間铆帽。
  • 與進(jìn)程相比,線程的創(chuàng)建和切換開銷更小德谅。由于啟動(dòng)一個(gè)新的線程必須給這個(gè)線程分配獨(dú)立的地址空間爹橱,建立許多數(shù)據(jù)結(jié)構(gòu)來維護(hù)線程代碼段、數(shù)據(jù)段等信息窄做,而運(yùn)行于同一個(gè)進(jìn)程內(nèi)的線程共享代碼段愧驱、數(shù)據(jù)段,線程的啟動(dòng)或切換的開銷比進(jìn)程少很多浸策。同時(shí)多線程在數(shù)據(jù)共享方面效率非常高
  • 多CPU或多核計(jì)算機(jī)本身就具有執(zhí)行多線程的能力冯键,在這些計(jì)算機(jī)上使用多線程能提高CPU的利用率。
  • 使用多線程能簡(jiǎn)化程序的結(jié)構(gòu)庸汗,使程序便于理解和維護(hù)惫确。

實(shí)現(xiàn)多線程的常用方法:

  • 繼承Thread類,重寫run()方法;
    Thread本質(zhì)上也是實(shí)現(xiàn)了Runnable接口的一個(gè)實(shí)例改化,它代表一個(gè)線程的實(shí)例掩蛤,并且,啟動(dòng)線程的唯一方法是通過Thread類的start()方法陈肛。start()方法是一個(gè)本地方法揍鸟,它將啟動(dòng)一個(gè)新線程,并執(zhí)行run()方法(Thread中提供的run()方法是一個(gè)空方法)句旱。這種方式通過自定義直接extends Thread阳藻,并重寫run()方法,就可以起到新線程并執(zhí)行自己定義的run()方法谈撒。調(diào)用start()方法后并不是執(zhí)行多線程代碼腥泥,而是使用該線程變?yōu)榭蛇\(yùn)行態(tài)(Runnable),什么時(shí)候運(yùn)行多線程代碼由操作系統(tǒng)決定啃匿。

  • 實(shí)現(xiàn)Runnable接口蛔外,并實(shí)現(xiàn)該接口run()方法;

    • 自定義類并實(shí)現(xiàn)Runnable接口溯乒,實(shí)現(xiàn)run()方法夹厌。
    • 創(chuàng)建Thread對(duì)象,用實(shí)現(xiàn)Runnable接口的對(duì)象作為實(shí)例化該Thread對(duì)象裆悄。
    • 調(diào)用Thread的start()方法矛纹。
class MyThread implements Runnable{
    public void run(){
        System.out.println("Thread body");
    }
}
public class Test{
    public static void main(String []args) {
        MyThread thread = new MyThread():
        Thread t = new Thread(thread);
        t.start();
    }
}

不管是通過繼承Thread類還是通過使用Runnable接口實(shí)現(xiàn)多線程的方法崖技,最終還是通過Thread的對(duì)象的API來控制線程的钟哥。

  • 實(shí)現(xiàn)Callable接口,重寫call()方法
    Callable泛型接口實(shí)際是屬于Executor框架中的功能類腻贰,有一個(gè)泛型參數(shù)V,Callable接口與Runnable接口的功能類似冀瓦,但提供了比Runnable更強(qiáng)大的功能。
    • Callable可以在任務(wù)結(jié)束后提供一個(gè)返回值(類型為V)的call()函數(shù)翼闽,Runnable無法提供這個(gè)功能洲炊。
    • Callable中的call()方法可以拋出異常尼啡,而Runnable無法提供這個(gè)功能询微。
    • 運(yùn)行Callable可以拿到一個(gè)Future對(duì)象,F(xiàn)uture對(duì)象表示異步計(jì)算的結(jié)果书聚,它提供了檢查計(jì)算是否完成的方法藻雌。由于線程屬于異步計(jì)算模型,因此無法從別的線程中得到函數(shù)的返回值蹦疑,在這種情況下,就可以使用Future來監(jiān)視目標(biāo)線程調(diào)用call()方法的情況,當(dāng)調(diào)用Future的get()方法以獲取結(jié)果時(shí)腔呜,當(dāng)前線程會(huì)阻塞,直到call()方法結(jié)束返回結(jié)果膝但。
public class CallableAndFuture{
    //創(chuàng)建線程類
    public static class CallableTest implements Callable<String> {
          public String call() throws Exception{
               return "Hello world!"
          }
    }
    public static void main(String []args) {
        ExecutorService threaPool = Executor.newSingleThreadExecutor();
        //啟動(dòng)線程
        Future<String> future = threadPool.submit(new CallableTest());
        try{
            System.out.println("waiting thread to finish!");
             System.out.println(future.get());//等待線程結(jié)束谤草,并獲取返回結(jié)果
        }
    }
}

注:
一般推薦實(shí)現(xiàn)Runnable接口的方式,原因是:

  • Thread類定義了多種方法可以被派生類使用或重寫丑孩。但是只有run()方法是必須被重寫的,在run()方法中實(shí)現(xiàn)這個(gè)線程的主要功能略贮。這當(dāng)然是實(shí)現(xiàn)Runnable接口所需要的方法仗岖。
  • 很多人認(rèn)為一個(gè)類僅在他們需要被加強(qiáng)或修改時(shí)才會(huì)被繼承,因此轧拄,如果沒有畢業(yè)重寫Thread類中的其他方法,那么通過繼承Thread的實(shí)現(xiàn)方式與實(shí)現(xiàn)Runnable接口的效果相同拄丰,在這種情況下最好通過實(shí)現(xiàn)Runnable接口的方式來創(chuàng)建線程。

run()方法與start()方法有什么區(qū)別
系統(tǒng)通過調(diào)用線程類的start()方法來啟動(dòng)一個(gè)線程愈案,此時(shí)該線程處于就緒狀態(tài),而非運(yùn)行狀態(tài)站绪,也就意味著這個(gè)線程可以被JVM來調(diào)度執(zhí)行,在調(diào)度過程中恢准,JVM通過調(diào)用線程類的run()方法來完成實(shí)際的操作做,當(dāng)run()方法結(jié)束后涂召,此線程就會(huì)終止敏沉。


多線程同步的實(shí)現(xiàn)方法

  • synchronized關(guān)鍵字
    在Java語言中,每個(gè)對(duì)象都有也給對(duì)象鎖與之關(guān)聯(lián)盟迟,該鎖表明對(duì)象在任何時(shí)候只允許被一個(gè)線程所擁有,當(dāng)一個(gè)線程調(diào)用對(duì)象的一段synchronized代碼時(shí)迫皱,需要先獲取這個(gè)鎖辖众,然后去執(zhí)行相應(yīng)的代碼,執(zhí)行結(jié)束后凹炸,釋放鎖。
    synchronized關(guān)鍵字主要有兩種用法(synchronized方法和synchronized塊)饲握,還可以用于靜態(tài)方法蚕键、類或某個(gè)實(shí)例,但對(duì)程序的效率影響很大锣光。
    • synchronized方法。在方法的聲明前加入synchronized關(guān)鍵字蹬刷。只要把多個(gè)線程對(duì)類需要被同步的資源的操作放到synchronized方法中,就能保證這個(gè)方法在同一時(shí)刻只能被一個(gè)線程訪問办成,從而保證了多線程訪問的安全性。然而迂卢,當(dāng)一個(gè)方法的方法體規(guī)模非常大時(shí),把該方法聲明為synchronized會(huì)大大影響程序的執(zhí)行效率靶壮。
    • synchronized塊。synchronized塊既可以把任意的代碼段聲明為synchronized腾降,也可以指定上鎖的對(duì)象碎绎,有非常高的靈活性。
synchronized(syncObject){
    //訪問syncObject的代碼
}
  • wait()方法和notify()方法
    在synchronized代碼被執(zhí)行期間映穗,線程可以調(diào)用對(duì)象的wait()方法,釋放對(duì)象鎖,進(jìn)入一個(gè)和該對(duì)象相關(guān)的等待池中宿接,并且可以調(diào)用notify()方法或notifyAll()方法通知正在等待的其他線程可以訪問。notify()方法僅喚醒一個(gè)線程(等待對(duì)列中的第一個(gè)線程)并允許它去獲得鎖梢卸,notifyAll()方法喚醒所有等待這個(gè)對(duì)象的線程并允許它們?nèi)カ@得鎖(所有線程根據(jù)優(yōu)先級(jí)獲得鎖)副女。必須放在synchronized塊中。
  • Lock
    • lock()以阻塞的方式獲取鎖碑幅,如果獲得鎖,立即返回恤批;如果別的線程持有鎖,當(dāng)前線程等待喜庞,直到獲得鎖后返回。
    • tryLock()以非阻塞的方式獲取鎖延都,只是嘗試性地獲取一下鎖,如果獲取到鎖晰房,立即返回true;否則月帝,返回false幽污。
    • tryLock(long timeout, TimeUnit unit)如果獲取了鎖,返回true距误。否則等待參數(shù)定的時(shí)間單元,在等待的過程中趁俊,如果獲取鎖,返回true寺擂;如果超時(shí)泼掠,返回false。
    • lockInterruptibly()如果獲取鎖择镇,立即返回true,如果沒有家坎,當(dāng)前線程處于休眠狀態(tài)吝梅,直到獲得鎖。

線程的wait()憔涉、sleep()、join()穿扳、yeild()

  • wait()上述
  • sleep()是Tread類的靜態(tài)方法衩侥,作用是使調(diào)用線程進(jìn)入睡眠狀態(tài)茫死。因?yàn)槭荰hread類的靜態(tài)方法履羞,因此它不能改變對(duì)象的機(jī)鎖。所以忆首,當(dāng)一個(gè)synchronized塊中調(diào)用sleep()方法時(shí),線程雖然休眠了详幽,但是對(duì)象的機(jī)鎖并沒有被釋放,其他線程無法訪問這個(gè)對(duì)象唇聘。sleep()方法必須捕抓異常柱搜,
  • join()等待目標(biāo)線程執(zhí)行完成之后 再繼續(xù)執(zhí)行
  • yeild()線程禮讓。目標(biāo)線程有運(yùn)行狀態(tài)轉(zhuǎn)換為就緒狀態(tài)也就是讓出執(zhí)行權(quán)限宪肖,讓跟其他線程得以優(yōu)先執(zhí)行,只會(huì)給相同優(yōu)先級(jí)或更高優(yōu)先級(jí)的線程以運(yùn)行機(jī)會(huì)匈庭。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末浑劳,一起剝皮案震驚了整個(gè)濱河市魔熏,隨后出現(xiàn)的幾起案子鸽扁,更是在濱河造成了極大的恐慌,老刑警劉巖桶现,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異相赁,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)钮科,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绵脯,“玉大人,你說我怎么就攤上這事赃承°睬郑” “怎么了?”我有些...
    開封第一講書人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵筒繁,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我毡咏,道長(zhǎng)逮刨,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任恢总,我火速辦了婚禮,結(jié)果婚禮上片仿,老公的妹妹穿的比我還像新娘尤辱。我一直安慰自己,他們只是感情好光督,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開白布结借。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪圃酵。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,610評(píng)論 1 305
  • 那天辜昵,我揣著相機(jī)與錄音咽斧,去河邊找鬼。 笑死舀锨,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的坎匿。 我是一名探鬼主播雷激,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼承桥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起凶异,我...
    開封第一講書人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤挤巡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后喉恋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瀑晒,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了轩褐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡勤讽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出脚牍,到底是詐尸還是另有隱情,我是刑警寧澤诸狭,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站芹彬,受9級(jí)特大地震影響叉庐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜陡叠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望译红。 院中可真熱鬧,春花似錦临庇、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至淳蔼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鹉梨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工晌坤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人骤菠。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像商乎,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鹉戚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355

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

  • 該文章轉(zhuǎn)自:http://blog.csdn.net/evankaka/article/details/44153...
    加來依藍(lán)閱讀 7,353評(píng)論 3 87
  • 寫在前面的話: 這篇博客是我從這里“轉(zhuǎn)載”的崩瓤,為什么轉(zhuǎn)載兩個(gè)字加“”呢?因?yàn)檫@絕不是簡(jiǎn)單的復(fù)制粘貼却桶,我花了五六個(gè)小...
    SmartSean閱讀 4,732評(píng)論 12 45
  • Java多線程學(xué)習(xí) [-] 一擴(kuò)展javalangThread類 二實(shí)現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 2,959評(píng)論 1 18
  • 本文主要講了java中多線程的使用方法颖系、線程同步、線程數(shù)據(jù)傳遞嘁扼、線程狀態(tài)及相應(yīng)的一些線程函數(shù)用法、概述等趁啸。 首先講...
    李欣陽(yáng)閱讀 2,456評(píng)論 1 15
  • 上一章 “我們家又不是孤兒院……而且根本說是對(duì)小孩影響很不好啊÷玫啵”女人扶著額頭很頭疼的樣子。 “我不也是你撿來的商虐?...
    Diedorkce閱讀 457評(píng)論 0 0