多線(xiàn)程基礎(chǔ)(一)

一、進(jìn)程和線(xiàn)程的概念

  • 進(jìn)程:運(yùn)行中的某個(gè)程序或者應(yīng)用,至少包含一個(gè)線(xiàn)程
  • 線(xiàn)程:進(jìn)程中負(fù)責(zé)執(zhí)行的一個(gè)或者多個(gè)執(zhí)行單元,歸屬于進(jìn)程,且多個(gè)線(xiàn)程共享進(jìn)程的資源
  • 并發(fā)機(jī)制:多個(gè)線(xiàn)程同時(shí)運(yùn)行,CPU給每個(gè)線(xiàn)程分配時(shí)間片,獲得時(shí)間的線(xiàn)程運(yùn)行,其他線(xiàn)程等待,由于時(shí)間片很短,從宏觀上看是線(xiàn)程都在運(yùn)行,微觀上看是線(xiàn)程走走停停

二、線(xiàn)程的創(chuàng)建

1、繼承Thread類(lèi),重寫(xiě)run()
public class MyThread extends Thread{
    private String name;
    MyThread(String name){
        this.name=name;
    }
    
    @Override
    public void run(){
        System.out.println("name"+name+",此線(xiàn)程的id為"+Thread.currentThread().getId());
    }
    
    public static void main(String[] args) {
        System.out.println("當(dāng)前主線(xiàn)程id為:"+Thread.currentThread().getId());
        MyThread myThread1 = new MyThread("線(xiàn)程1");
        myThread1.start();
        MyThread myThread2 = new MyThread("線(xiàn)程2");
        myThread2.run();
        
    }
}

輸出如下:

image.png

小結(jié):

  • start()和run()方法的不同。start是啟動(dòng)線(xiàn)程,交給CPU去獲取時(shí)間片并調(diào)用run方法。而用run方法相當(dāng)于交給主線(xiàn)程去執(zhí)行run,并不會(huì)創(chuàng)建新的線(xiàn)程。
  • 線(xiàn)程1是先創(chuàng)建的,但是輸出結(jié)果在后,說(shuō)明線(xiàn)程的創(chuàng)建并不會(huì)阻塞主線(xiàn)程的執(zhí)行
2、實(shí)現(xiàn)Runnable接口
public class MyRunnable implements Runnable {
    private String name;
    MyRunnable(String name){
        this.name = name;
    }
    public void run() {
        System.out.println("啟動(dòng)"+name+":id為"+Thread.currentThread().getId());
    }
    
    public static void main(String[] args) {
        MyRunnable my = new MyRunnable("runnable線(xiàn)程");
        Thread thread = new Thread(my);
        thread.start();
    }
}
3、最簡(jiǎn)潔的啟動(dòng)線(xiàn)程的方式
new Thread(new Runnable(){
  public void run(){
        xxxxxx
  }
};).start();

三、線(xiàn)程的狀態(tài)

  • 創(chuàng)建(new)狀態(tài): 準(zhǔn)備好了一個(gè)多線(xiàn)程的對(duì)象
  • 就緒(runnable)狀態(tài): 調(diào)用了start()方法, 等待CPU進(jìn)行調(diào)度
  • 運(yùn)行(running)狀態(tài): 執(zhí)行run()方法
  • 阻塞(blocked)狀態(tài): 暫時(shí)停止執(zhí)行, 可能將資源交給其它線(xiàn)程使用
  • 終止(dead)狀態(tài): 線(xiàn)程銷(xiāo)毀
image.png

1、當(dāng)線(xiàn)程進(jìn)入就緒狀態(tài)后,要等CPU分配到時(shí)間片之后,線(xiàn)程便真正進(jìn)入運(yùn)行狀態(tài)。
2、線(xiàn)程在運(yùn)行狀態(tài)過(guò)程中,可能有多個(gè)原因?qū)е庐?dāng)前線(xiàn)程不繼續(xù)運(yùn)行下去,比如用戶(hù)主動(dòng)讓線(xiàn)程睡眠(睡眠一定的時(shí)間之后再重新執(zhí)行)、用戶(hù)主動(dòng)讓線(xiàn)程等待,或者被同步塊給阻塞,此時(shí)就對(duì)應(yīng)著多個(gè)狀態(tài):time waiting(睡眠或等待一定的事件)、waiting(等待被喚醒)、blocked(阻塞)。
3、當(dāng)由于突然中斷或者子任務(wù)執(zhí)行完畢,線(xiàn)程就會(huì)被消亡。

注:sleep和wait的區(qū)別:

  • sleep是Thread類(lèi)的方法,wait是Object類(lèi)中定義的方法.
  • Thread.sleep不會(huì)導(dǎo)致鎖行為的改變, 如果當(dāng)前線(xiàn)程是擁有鎖的, 那么
    Thread.sleep不會(huì)讓線(xiàn)程釋放鎖.
  • Thread.sleep和Object.wait都會(huì)暫停當(dāng)前的線(xiàn)程. OS會(huì)將執(zhí)行時(shí)間分配給其它線(xiàn)程. 區(qū)別是, 調(diào)用wait后, 需要?jiǎng)e的線(xiàn)程執(zhí)行notify/notifyAll才能夠重新獲得CPU執(zhí)行時(shí)間.

四、線(xiàn)程API

1、sleep():線(xiàn)程休眠,且不會(huì)釋放鎖。
public class MyThreadAPI{
    private int i = 0;
    private Object object = new Object();
    
    public static void main(String[] args) {
        MyThreadAPI api = new MyThreadAPI();
        MyThreadSleep thread1 = api.new MyThreadSleep() ;
        MyThreadSleep thread2 = api.new MyThreadSleep() ;
        thread1.start();
        thread2.start();
    }
    class MyThreadSleep extends Thread{
        public void run(){
            synchronized (object) {
                i++;
                System.out.println(Thread.currentThread().getName()+"睡眠前i:"+i);
                System.out.println(Thread.currentThread().getName()+"進(jìn)入睡眠");
                try {
                    Thread.currentThread().sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"睡眠結(jié)束");
                i++;
                System.out.println(Thread.currentThread().getName()+"睡眠后i:"+i);
            }
        }
    }
}

輸出結(jié)果:


image.png
2、yield(),讓出當(dāng)前時(shí)間片,與sleep不同的是不可選擇時(shí)間
public class MyThreadYeild extends Thread {
    public void run(){
        long start = System.currentTimeMillis();
        int count = 0;
        for(int i = 1;i<50000000;i++){
            count++;
            Thread.yield();
        }
        System.out.println("當(dāng)前count為:"+count);
        long end = System.currentTimeMillis();
        System.out.println("耗時(shí):"+(end-start)+"毫秒");
    }
    public static void main(String[] args) {
        MyThreadYeild thread = new MyThreadYeild();
        thread.start();
    }
}

輸出可發(fā)現(xiàn):不寫(xiě)thread.yield()方法時(shí),執(zhí)行時(shí)間較短

線(xiàn)程的sleep()方法和yield()方法有什么區(qū)別?
① sleep()方法給其他線(xiàn)程運(yùn)行機(jī)會(huì)時(shí)不考慮線(xiàn)程的優(yōu)先級(jí),因此會(huì)給低優(yōu)先級(jí)的線(xiàn)程以運(yùn)行的機(jī)會(huì);yield()方法只會(huì)給相同優(yōu)先級(jí)或更高優(yōu)先級(jí)的線(xiàn)程以運(yùn)行的機(jī)會(huì);
② 線(xiàn)程執(zhí)行sleep()方法后轉(zhuǎn)入阻塞(blocked)狀態(tài),而執(zhí)行yield()方法后轉(zhuǎn)入就緒(ready)狀態(tài);
③ sleep()方法聲明拋出InterruptedException,而yield()方法沒(méi)有聲明任何異常;
④ sleep()方法比yield()方法(跟操作系統(tǒng)CPU調(diào)度相關(guān))具有更好的可移植性。

3、join()方法

主線(xiàn)程創(chuàng)建并啟動(dòng)了線(xiàn)程,如果子線(xiàn)程中要進(jìn)行大量耗時(shí)運(yùn)算,主線(xiàn)程往往將早于子線(xiàn)程結(jié)束之前結(jié)束。這時(shí),如果主線(xiàn)程想等待子線(xiàn)程執(zhí)行完成之后再結(jié)束,比如子線(xiàn)程處理一個(gè)數(shù)據(jù),主線(xiàn)程要取得這個(gè)數(shù)據(jù)中的值,就要用到j(luò)oin()方法了。方法join()的作用是等待線(xiàn)程對(duì)象銷(xiāo)毀。

public class MyThread4 extends Thread {
    public MyThread4(String name){
        super(name);
    }
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(getName() + "  " + i);
        }
    }
    public static void main(String[] args) throws InterruptedException {
        // 啟動(dòng)子進(jìn)程
        for (int i = 0; i < 10; i++) {
            if (i == 5) {
                MyThread4 th = new MyThread4("joined thread");
                th.start();
                th.join();
            }
        System.out.println(Thread.currentThread().getName() + "  " + i);
        }
    }
}

輸出如下:


image.png
4、interrupt線(xiàn)程中斷

public void interrupt(); 中斷線(xiàn)程。
public static boolean interrupted(); 是一個(gè)靜態(tài)方法,用于測(cè)試當(dāng)前線(xiàn)程是否已經(jīng)中斷,并將線(xiàn)程的中斷狀態(tài) 清除。所以如果線(xiàn)程已經(jīng)中斷,調(diào)用兩次interrupted,第二次時(shí)會(huì)返回false,因?yàn)榈谝淮畏祷豻rue后會(huì)清除中斷狀態(tài)。

五、守護(hù)線(xiàn)程

線(xiàn)程分為用戶(hù)線(xiàn)程和守護(hù)線(xiàn)程,當(dāng)用戶(hù)線(xiàn)程結(jié)束,守護(hù)線(xiàn)程會(huì)被強(qiáng)制終止。GC就是守護(hù)線(xiàn)程,默認(rèn)線(xiàn)程是用戶(hù)線(xiàn)程,在啟動(dòng)前可設(shè)置為守護(hù)

參考:
http://www.importnew.com/21136.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評(píng)論 6 546
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,814評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 178,980評(píng)論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 64,064評(píng)論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,779評(píng)論 6 414
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 56,109評(píng)論 1 330
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評(píng)論 3 450
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 43,287評(píng)論 0 291
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,799評(píng)論 1 338
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,515評(píng)論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,750評(píng)論 1 375
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評(píng)論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,933評(píng)論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 35,327評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,667評(píng)論 1 296
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,492評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,703評(píng)論 2 380

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

  • 線(xiàn)程的簡(jiǎn)介 幾乎每種操作系統(tǒng)都支持進(jìn)程的概念。進(jìn)程就是在某種程度上相互隔離的、獨(dú)立運(yùn)行的程序。線(xiàn)程化是允許多個(gè)活動(dòng)...
    小人物灌籃閱讀 685評(píng)論 2 4
  • 前言 多線(xiàn)程并發(fā)編程是Java編程中重要的一塊內(nèi)容,也是面試重點(diǎn)覆蓋區(qū)域,所以學(xué)好多線(xiàn)程并發(fā)編程對(duì)我們來(lái)說(shuō)極其重要...
    嘟爺MD閱讀 7,333評(píng)論 21 272
  • 本文主要講了java中多線(xiàn)程的使用方法、線(xiàn)程同步、線(xiàn)程數(shù)據(jù)傳遞、線(xiàn)程狀態(tài)及相應(yīng)的一些線(xiàn)程函數(shù)用法、概述等。 首先講...
    李欣陽(yáng)閱讀 2,482評(píng)論 1 15
  • Java多線(xiàn)程學(xué)習(xí) [-] 一擴(kuò)展javalangThread類(lèi) 二實(shí)現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 2,981評(píng)論 1 18
  • 寫(xiě)在前面的話(huà): 這篇博客是我從這里“轉(zhuǎn)載”的,為什么轉(zhuǎn)載兩個(gè)字加“”呢?因?yàn)檫@絕不是簡(jiǎn)單的復(fù)制粘貼,我花了五六個(gè)小...
    SmartSean閱讀 4,776評(píng)論 12 45