Java多線程機制——多線程概述

本文概述

本篇文章將分四塊內(nèi)容對Java中的多線程機制進行介紹:
一. 多線程概述
二. 實現(xiàn)多線程的兩種方式
三. 多線程的生命周期
四. 線程調(diào)度和控制

一. 線程與進程的概述

??線程是依賴于進程而存在的圈驼,因此在討論線程之前吓揪,我們必須要知道什么是進程

1. 什么是進程

??進程就是正在運行的程序,是系統(tǒng)進行資源分配和調(diào)用的獨立單位充包。每一個進程都有它自己的內(nèi)存空間和系統(tǒng)資源。當我們打開電腦資源管理器時帆疟,就可以顯示當前正在運行的所有進程粟按。

2. 多進程的意義

??大家應該有過這樣的經(jīng)歷:我可以同時在電腦上做很多事情,比如我可以一邊玩游戲遏餐,一邊聽音樂伦腐,網(wǎng)速夠快我還可以同時用迅雷下載電影赢底。這是因為我們的操作系統(tǒng)支持多進程失都,簡而言之就是:能在同一時段內(nèi)執(zhí)行多個任務
??需要注意的是,對于單核計算機來講幸冻,游戲和聽音樂這兩個任務并不是“同時進行”的粹庞,因為CPU在某個時間點上只能做一件事情,計算機是在游戲進程和音樂進程間做著頻繁切換洽损,且切換速度很快(也就是輪流執(zhí)行CPU時間片)庞溜,所以,我們感覺游戲和音樂好像在“同時”進行,其實并不是同時執(zhí)行的流码。

CPU占用率
??多進程的作用不是提高執(zhí)行速度又官,而是提高CPU的使用率

3. 什么是多線程

??在一個進程內(nèi)部又可以執(zhí)行多個任務,而這每一個任務我們就可以看成是一個線程漫试。
??下面是一段代碼示例:

public class Demo {
     public static void main(String args[]) {
              //代碼段1
              do();
              //代碼段2 
          }
      public static void do() { 
              //代碼段11

              function1();
              function2();
              //代碼段22
          }
      public static void function1(){...}
      public static void function2(){...}
}

如果是單線程的執(zhí)行方式:是一條執(zhí)行路徑


單線程方式.png

如果是多線程的執(zhí)行方式:有多條執(zhí)行路徑


多線程方式.png
  1. 是進程中的單個順序控制流六敬,是一條執(zhí)行路徑。
  2. 一個進程如果只有一條執(zhí)行路徑驾荣,則稱為單線程程序外构。
  3. 一個進程如果有多條執(zhí)行路徑,則稱為多線程程序播掷。

4. 多進程的意義

??多線程的作用不是提高執(zhí)行速度审编,而是為了提高應用程序的使用率。

并行:邏輯上同時發(fā)生歧匈,指在某一段時間段同時運行多段程序
并發(fā):物理上同時發(fā)生垒酬,指在某一個時間點同時運行多段程序

??多線程卻給了我們一個錯覺:讓我們認為多個線程是并發(fā)執(zhí)行的。其實不是:多個線程共享同一個進程的資源眯亦,但是棧內(nèi)存是獨立的伤溉,一個線程一個棧。所以他們?nèi)匀皇窃趽孋PU的資源執(zhí)行妻率。一個時間點上只有能有一個線程執(zhí)行乱顾。而且誰搶到,這個不一定宫静,所以走净,造成了線程運行的隨機性其中的某一個進程如果執(zhí)行路徑比較多的話孤里,就會有更高的幾率搶到CPU的執(zhí)行權(quán)伏伯。

5. Java中的多線程

??Java程序運行會啟動JVM,相當于啟動了一個進程捌袜,該進程會自動啟動一個 “主線程” 说搅,而main方法就運行在這個主線程當中,所以我們之前寫的程序都是單線程虏等。

思考:JVM啟動是單線程還是多線程弄唧?
答案:多線程,JVM一定會啟動主線程和垃圾處理機制霍衫,所以一定是多線程

二. 實現(xiàn)多線程的兩種方式

1. 多線程實現(xiàn)方式V1.0(繼承Thread類)

根據(jù)API文檔查詢可以得到創(chuàng)建多線程的方法:

  1. 自定義類繼承Thread類
  2. 該子類重寫子類的run()方法
  3. 并啟動該子類的實例候引。
  4. 調(diào)用實例的start方法

放在run方法中的代碼會被線程執(zhí)行

注意:run()方法實際上是單線程,不能直接調(diào)用run()方法敦跌,要先看到多線程的效果澄干,必須使用start()方法蔚润。run()僅僅只是被封裝的執(zhí)行代碼裸弦,而是普通方法辐啄,然而start方法會先啟用線程吵瞻,然后再用jvm去調(diào)用線程的run方法
因此:要啟動多線程,一定要調(diào)用start()方法从媚,不能使用run()方法

子線程1(Thread1):
public class FirstThread extends Thread{
    public void run() {
        for(int i = 0; i < 100; i++) {
            System.out.println("Thread1\t" + i);
        }
    }
}
子線程2(Thread2):
public class SecondThread extends Thread{
    public void run() {
        for(int i = 0; i < 100; i++) {
            System.out.println("Thread2\t" + i);
        }
    }
}
main函數(shù)
public class MyThreadDemo {
    public static void main(String args[]) {
        Thread t1 = new FirstThread();
        Thread t2 = new SecondThread();
        t1.start();
        t2.start();
    }
}

2. 多線程實現(xiàn)方式V2.0(實現(xiàn)Runnable接口)

  1. 自定義類MyRunnerble()實現(xiàn)Runnable接口
  2. 在MyRunnerble中重寫run()方法
  3. 創(chuàng)建MyRunnerble的實例對象
  4. 將所創(chuàng)建的對象作為參數(shù)傳入到Thread當中
public class MyThreadDemo2 {
    public static void main(String args[]) {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i = 0; i < 100; i++) {
                    System.out.println("thread1" + i);
                }
            }
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i = 0;i < 100; i++) {
                    System.out.println("thread2" + i);
                }
            }
        });
        t1.start();
        t2.start();
    }
}

3. 兩種創(chuàng)建方式的比較

??既然有了方式一搂誉,為什么又要有方式二呢?
??比較兩種創(chuàng)建方式静檬,我們不難發(fā)現(xiàn)炭懊,第一種方式是通過繼承的方式實現(xiàn)的,第二種方式是通過接口的方式實現(xiàn)拂檩。

繼承Runnerble接口的優(yōu)點:
??1. 可以避免Java單繼承帶來的局限性侮腹。
??2. 適合多個相同程序的代碼去處理同一個資源的情況,把線程同程序的代碼稻励,數(shù)據(jù)有效的分離父阻,較好體現(xiàn)了面向?qū)ο蟮脑O(shè)計思想。

三. 多線程的生命周期

??多線程的生命周期如下圖所示:


線程生命周期圖.png

四. 線程調(diào)度和控制

1. 線程調(diào)度

??如果我們的計算機只有一個 CPU望抽,那么 CPU 在某一個時刻只能執(zhí)行一條指令加矛,線程只有得到 CPU時間片,也就是使用權(quán)煤篙,才可以執(zhí)行指令斟览。那么Java是如何對線程進行調(diào)用的呢?

線程調(diào)度的兩種模式

  1. 分時調(diào)度模式:所有線程輪流使用 CPU 的使用權(quán)辑奈,平均分配每個線程占用 CPU 的時間片苛茂。
  2. 搶占式調(diào)度模型:優(yōu)先讓優(yōu)先級高的線程使用 CPU,如果線程的優(yōu)先級相同鸠窗,那么會隨機選擇一個妓羊,優(yōu)先級高的線程獲取的 CPU 時間片相對多一些。

Java采用的是搶占式調(diào)度模式稍计,用優(yōu)先級控制時間片輪轉(zhuǎn)躁绸。
設(shè)置和獲取優(yōu)先級的方式如下:

public final int getPriority()
public final void setPriority(int newPriority)

2. 線程的控制

2.1 線程休眠

??相當于在線程中暫停了幾秒

方法:
public static void sleep(long millis)
示例
public class SecondThread extends Thread{
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
            System.out.println("線程2");
    }
}
注意

該方法是靜態(tài)方法,可以通過類直接調(diào)用臣嚣,而且會拋出異常净刮。

2.2 線程加入

為了讓某些需要執(zhí)行的線程執(zhí)行完畢,別的線程才能拿夠繼續(xù)

方法
public final void join()
示例
public class MyThreadDemo {
    public static void main(String args[]) {
        Thread t1 = new FirstThread();
        Thread t2 = new SecondThread();
        t1.start();
        try {
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t2.start();
    }
}
注意

只有當t1線程執(zhí)行完畢之后才會執(zhí)行第二個線程茧球,要注意該方法也會拋出異常庭瑰。

2.3 線程禮讓

暫停執(zhí)行當前線程星持,并執(zhí)行其他線程抢埋,在一定的程度上能夠交替執(zhí)行,但不能保證一定是交替執(zhí)行的

方法
public static void yield()
注意

使用方法與之前類似,該方法是靜態(tài)方法揪垄,所以直接可以通過類調(diào)用

2.4 后臺線程(守護線程)

將該線程標記為守護線程或者是用戶線程穷吮,當正在運行的線程都是守護線程時,java虛擬機退出饥努。

方法
public final void setDaemon(boolean on)
示例:
public class MyThreadDemo {
    public static void main(String args[]) {
        Thread t1 = new FirstThread();
        Thread t2 = new SecondThread();
        Thread t3 = new ThirdThread();
        t1.setDaemon(true);//將t1設(shè)置為守護進程
        t2.setDaemon(true);//將t2設(shè)置為守護進程
        t1.start();
        t2.start();
        t3.start();
    }
}
注意:

該方法只能夠在開啟線程之前使用捡鱼,而且不能立即停止,有一定的延遲酷愧。

2.5 線程中斷

中途關(guān)閉線程

方法
public final void stop()//過時了驾诈,但是還是可以使用的,不安全不建議使用
public void interrupt()//他讓我們拋出一個異常溶浴,如果受阻乍迄,那么狀態(tài)終止,拋出異常

總結(jié)

??多線程是Java各種機制中非常重要也是比較陌生的一塊內(nèi)容士败,需要對計算機操作系統(tǒng)運行機制有一定了解的情況下才能深入理解闯两,之后的文章會對多線程的安全,死鎖和與線程有關(guān)的設(shè)計模式做更深入的介紹谅将,歡迎繼續(xù)觀看后續(xù)內(nèi)容漾狼,一起體會Java語言的智慧與魅力。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末饥臂,一起剝皮案震驚了整個濱河市逊躁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌隅熙,老刑警劉巖志衣,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異猛们,居然都是意外死亡念脯,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門弯淘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绿店,“玉大人,你說我怎么就攤上這事庐橙〖傥穑” “怎么了?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵态鳖,是天一觀的道長转培。 經(jīng)常有香客問我,道長浆竭,這世上最難降的妖魔是什么浸须? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任惨寿,我火速辦了婚禮,結(jié)果婚禮上删窒,老公的妹妹穿的比我還像新娘裂垦。我一直安慰自己,他們只是感情好肌索,可當我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布蕉拢。 她就那樣靜靜地躺著,像睡著了一般诚亚。 火紅的嫁衣襯著肌膚如雪晕换。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天站宗,我揣著相機與錄音届巩,去河邊找鬼。 笑死份乒,一個胖子當著我的面吹牛恕汇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播或辖,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼瘾英,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了颂暇?” 一聲冷哼從身側(cè)響起缺谴,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎耳鸯,沒想到半個月后湿蛔,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡县爬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年阳啥,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片财喳。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡察迟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出耳高,到底是詐尸還是另有隱情扎瓶,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布泌枪,位于F島的核電站概荷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏碌燕。R本人自食惡果不足惜误证,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一继薛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧雷厂,春花似錦、人聲如沸叠殷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽林束。三九已至像棘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間壶冒,已是汗流浹背缕题。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留胖腾,地道東北人烟零。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像咸作,于是被迫代替她去往敵國和親锨阿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,864評論 2 354

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

  • 前言 多線程并發(fā)編程是Java編程中重要的一塊內(nèi)容记罚,也是面試重點覆蓋區(qū)域墅诡,所以學好多線程并發(fā)編程對我們來說極其重要...
    嘟爺MD閱讀 7,315評論 21 272
  • 又來到了一個老生常談的問題,應用層軟件開發(fā)的程序員要不要了解和深入學習操作系統(tǒng)呢桐智? 今天就這個問題開始末早,來談談操...
    tangsl閱讀 4,125評論 0 23
  • 本文主要講了java中多線程的使用方法、線程同步说庭、線程數(shù)據(jù)傳遞然磷、線程狀態(tài)及相應的一些線程函數(shù)用法、概述等刊驴。 首先講...
    李欣陽閱讀 2,454評論 1 15
  • Java多線程學習 [-] 一擴展javalangThread類 二實現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 2,957評論 1 18
  • 個人運動 這一周最高紀錄4.6样屠,17號回家,早上收拾東西沒有跑步缺脉。反思痪欲,其實是自己找借口,不把重要的事情優(yōu)先去做攻礼,...
    lijutong_010閱讀 212評論 0 2