Java——Thread線程基礎(chǔ)知識(shí)學(xué)習(xí)

1.進(jìn)程與線程

一個(gè)程序中至少有一個(gè)進(jìn)程伤溉,一個(gè)進(jìn)程中至少會(huì)有一個(gè)線程较解。一個(gè)進(jìn)程可以包含多個(gè)線程撩嚼。

看到一個(gè)蠻容易理解的比方:

cpu可以看做一個(gè)工廠捆憎,而進(jìn)程可以看做是一個(gè)車(chē)間按咒,每次這個(gè)工廠只能有一個(gè)車(chē)間工作迟隅,一旦有一個(gè)車(chē)間工作其他車(chē)間就需要停止工作。也就是說(shuō)在任何時(shí)候励七,cpu都只運(yùn)行一個(gè)進(jìn)程智袭。線程就是車(chē)間里的工人,一個(gè)車(chē)間可以有多個(gè)工人同時(shí)工作掠抬,他們可以協(xié)調(diào)共同完成一個(gè)任務(wù)吼野。而車(chē)間內(nèi)的房間,工人們是共享的,車(chē)間內(nèi)的工人們都可以進(jìn)出两波。這也就意味著一個(gè)進(jìn)程的內(nèi)存空間瞳步,線程是共享的闷哆。車(chē)間內(nèi)的房間大小不等,有的房間只能容下一個(gè)人单起,其他人想使用這個(gè)房間的話抱怔,只有這個(gè)小房間內(nèi)人出去后才可以。這代表一個(gè)線程使用某些共享內(nèi)存時(shí)嘀倒,其他線程必須等它結(jié)束屈留,才能使用這一塊內(nèi)存。

以上的理解是看到這篇博客進(jìn)程與線程的一個(gè)簡(jiǎn)單解釋寫(xiě)的通俗易懂测蘑,配圖特別形象灌危。


2.Thread類(lèi)

Thread 狀態(tài):

  • 創(chuàng)建(new): 使用new的方式創(chuàng)建一個(gè)Thread對(duì)象。
  • 就緒(runnable) :線程對(duì)象調(diào)用start()方法帮寻,進(jìn)入就緒狀態(tài)乍狐,此時(shí)的線程位于可運(yùn)行池中,等待cpu調(diào)度固逗,獲取cpu的使用權(quán)
  • 運(yùn)行(running):獲取到cpu的使用權(quán)浅蚪,占用cpu,執(zhí)行run方法中的代碼
  • 阻塞(blocked):運(yùn)行狀態(tài)的線程烫罩,遇到阻塞事件惜傲,進(jìn)入阻塞狀態(tài),此時(shí)虛擬機(jī)不會(huì)再給線程分配cpu贝攒。當(dāng)阻塞狀態(tài)解除時(shí)盗誊,進(jìn)入就緒狀態(tài)。

阻塞狀態(tài)又分幾種種情況:1)位于對(duì)象等待池中的阻塞狀態(tài)隘弊,也就是調(diào)用wait()方法哈踱;2)對(duì)象鎖中的阻塞狀態(tài),在使用某個(gè)對(duì)象的同步鎖時(shí)梨熙,該對(duì)象的同步鎖已經(jīng)被其他線程占用开镣;3).使用了sleep()方法或者join()方法

Thread的狀態(tài)

2.1 兩種創(chuàng)建線程的方式

創(chuàng)建一個(gè)線程一共有三種方式,其中兩種常見(jiàn)的是:

  1. 繼承Thread類(lèi)
  2. 實(shí)現(xiàn)Runnable接口

2.1.1繼承Thread類(lèi)

class MyThread_1 extends Thread {
    public MyThread_1(String name) {
         super(name);
     }
    @Override
    public void run() {
        System.out.println(System.currentTimeMillis());
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName()+"---->" + i);
        }
        System.out.println(System.currentTimeMillis());
    }
}

開(kāi)啟線程就是:
new MyThread_1("thread_1").start()

Thread的構(gòu)造方法有8種咽扇,常見(jiàn)的也就4種:

  • Thread()
  • Thread(Runnable target)
  • Thread(Runnable target, String name)
  • Thread(String name)

2.1.2實(shí)現(xiàn)Runnable接口

class Ticket implements Runnable {
    private int num = 100;
    @Override
    public void run() {
        while (true) {
            if (num > 0) {
                    System.out.println("--->" + num--);
            }
        }
    }
}

開(kāi)啟線程就是:
new Thread(new Ticket()).start()

受限于Java單繼承可多實(shí)現(xiàn)的特點(diǎn)邪财,一般都常用第二種方式,往往也是直接采用匿名內(nèi)部類(lèi)质欲。


2.2 Thread類(lèi)的常見(jiàn)方法

  • setName(String name) getName()

給Thread設(shè)置自定義的名字树埠。也可以采用構(gòu)造方法傳值。對(duì)應(yīng)的便是拿到Thread的名字嘶伟。如果不設(shè)置線程的名字怎憋,拿到的默認(rèn)名字是"Thread-0,1,2..."。

  • currentThread()

獲取當(dāng)前線程

  • start()

開(kāi)啟線程九昧。啟動(dòng)線程后绊袋,開(kāi)始執(zhí)行run()方法中的代碼赠橙。

  • setPriority(int newPriority) getPriority()

為線程設(shè)置優(yōu)先級(jí)。優(yōu)先級(jí)從1到10愤炸。默認(rèn)是5。

  • sleep(long millis)

休眠毫秒數(shù)

  • join()

線程加入或者線程合并掉奄,加入的線程執(zhí)行結(jié)束才會(huì)執(zhí)行其他的線程规个。

  • yield()

線程讓步,暫停當(dāng)前正在執(zhí)行的線程姓建,把執(zhí)行權(quán)給其他線程诞仓,執(zhí)行其他的線程

  • interrupt()

中斷線程。并不是停止一個(gè)線程速兔,給線程加一個(gè)中斷標(biāo)記墅拭。使線程從阻塞(凍結(jié))狀態(tài)到運(yùn)行狀態(tài)。

  • isInterrupted()

判斷線程是否中斷成功涣狗。


上面的幾個(gè)方法谍婉,也都是簡(jiǎn)單學(xué)習(xí)。了解并不深入镀钓。

2.3線程全問(wèn)題

上面的比方中說(shuō)穗熬,線程就像車(chē)間的工人,而車(chē)間內(nèi)的房間工人們都可以出入的丁溅。當(dāng)多個(gè)工人同時(shí)工作時(shí)唤蔗,有時(shí)需要使用同一個(gè)房間內(nèi)的原材料,如果多名對(duì)原材料有操作資格的工人同時(shí)都進(jìn)入這個(gè)房間的話窟赏,都同時(shí)對(duì)材料進(jìn)行操作會(huì)存在安全隱患妓柜,這時(shí)就需要考慮給這個(gè)的房間設(shè)置一些限制,只有在沒(méi)人使用原材料的情況下涯穷,有操作資格的工人才可以進(jìn)入棍掐。一旦有一名工人在對(duì)原材料進(jìn)行操作,其他工人就要等待求豫,直到房間內(nèi)對(duì)原材料進(jìn)行操作的工人出來(lái)塌衰,下一名對(duì)原材料有操作資格的工人才可以進(jìn)入。

也就是說(shuō)多線程在一些情況下會(huì)出一些安全情況蝠嘉。


2.3.1同步鎖

當(dāng)多個(gè)線程要同時(shí)操作一個(gè)共享的數(shù)據(jù)最疆,共享數(shù)據(jù)執(zhí)行過(guò)程中還進(jìn)行了變換,其中一個(gè)線程正在對(duì)共享數(shù)據(jù)進(jìn)行操作變換時(shí)蚤告,沒(méi)有執(zhí)行結(jié)束努酸,另外一個(gè)線程就參與進(jìn)來(lái),就會(huì)導(dǎo)致共享數(shù)據(jù)的操作錯(cuò)誤杜恰。這個(gè)安全問(wèn)題其實(shí)就是大名鼎鼎的生產(chǎn)者消費(fèi)者問(wèn)題获诈。

解決的思路就是每次只允許一個(gè)線程進(jìn)行共享數(shù)據(jù)的操作仍源,加入了同步鎖。

public class Thread_2 {

    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        Thread t_1 = new Thread(ticket, "one");
        Thread t_2 = new Thread(ticket, "two");
        
        t_1.start();
        t_2.start();
        
    }

}

class Ticket implements Runnable {
    private int num = 100;
    
    @Override
    public void run() {
        while (true) {
            synchronized (Ticket.this) {
                if (num > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "--->" + num--);
                }
            }
        }
    }
}

2.3.2 關(guān)于wait舔涎,notify笼踩,notiryAll

需要注意的是,wait(),notify(),notifyall()這幾個(gè)方法并不是Thread類(lèi)中的亡嫌,而是Objecet類(lèi)的嚎于。這幾個(gè)方法是根據(jù)需要有時(shí)要用在同步鎖中,同步鎖的對(duì)象是可以為任何對(duì)象的挟冠。在同步代碼塊中于购,調(diào)用這些方法是需要同步鎖對(duì)象的,如果這3個(gè)方法是在Thread類(lèi)中知染,就不符合實(shí)際的需要肋僧,不滿足能夠被任意同步鎖調(diào)用。

貼一個(gè)學(xué)習(xí)時(shí)控淡,敲的代碼:

public class Thread_3 {
    public static void main(String[] args) {
        Person person = new Person();

        new Thread(new Input(person)).start();
        new Thread(new Output(person)).start();

    }
}

class Input implements Runnable {
    private Person person;

    public Input(thread_demo.Person person) {
        this.person = person;
    }

    @Override
    public void run() {
        if (person != null) {
            int x = 0;
            while (true) {

                if (x == 0) {
                    person.set("Java", "22");
                } else {
                    person.set("李四", "五");
                }

                x = (x + 1) % 2;

            }
        }
    }
}

class Output implements Runnable {
    private Person person;

    public Output(Person person) {
        this.person = person;
    }

    @Override
    public void run() {
        if (person != null) {
            while (true) {
                person.out();
            }
        }
    }

}

class Person {
    private String name;
    private String age;
    private boolean flag;

    public synchronized void set(String name, String age) {
        while (flag) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.name = name;
        this.age = age;
        flag = true;
        this.notifyAll();
    }

    public synchronized void out() {
        while (!flag) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(name + "--->" + age);
        flag = false;
        this.notifyAll();
    }
}

2.3.3單例模式-懶漢式 防止多線程創(chuàng)建多個(gè)對(duì)象

public class Singleton {
    private static Singleton singleton = null;

    private Singleton() {};

    public static Singleton getInstance() {
        if (singleton == null) {//為了減少對(duì)同步鎖的判斷 
            synchronized (Singleton.class) {//靜態(tài)方法中沒(méi)有this
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

最后

一直以來(lái)就感覺(jué)多線程是個(gè)很難的東西嫌吠。大三學(xué)習(xí)Java課程老師上課講解生產(chǎn)者消費(fèi)者時(shí),覺(jué)得好復(fù)雜啊逸寓,多線程果然好難居兆。雖然現(xiàn)在工作經(jīng)驗(yàn)不多,但時(shí)隔一年半竹伸,再來(lái)看這個(gè)問(wèn)題時(shí)泥栖,也顯得不那么復(fù)雜了。不過(guò)勋篓,對(duì)于多線程依然覺(jué)得很難吧享。目前對(duì)于線程的狀態(tài)還不是很清晰

在我目前的Android開(kāi)發(fā)經(jīng)驗(yàn)中,對(duì)于多線程的使用不多譬嚣,雖然Android中不允許在UI主線程來(lái)進(jìn)行網(wǎng)絡(luò)請(qǐng)求钢颂,但目前各個(gè)網(wǎng)絡(luò)請(qǐng)求框架都有對(duì)異步線程封裝,結(jié)合Handler便可以實(shí)現(xiàn)對(duì)UI內(nèi)容的更新拜银,顯示網(wǎng)絡(luò)請(qǐng)求拿到的數(shù)據(jù)殊鞭。目前對(duì)Thread的了解比較淺顯。

使用的場(chǎng)景也往往比較簡(jiǎn)單尼桶。記得比較清楚的兩個(gè)場(chǎng)景操灿,一個(gè)開(kāi)啟一個(gè)線程用來(lái)計(jì)時(shí),一個(gè)用于實(shí)現(xiàn)廣告頁(yè)無(wú)限輪播泵督。感覺(jué)這兩個(gè)使用場(chǎng)景也可以用Android中的Handler來(lái)代替趾盐,而且實(shí)現(xiàn)過(guò)程也相對(duì)簡(jiǎn)單。接下來(lái)打算用兩種方式再來(lái)實(shí)現(xiàn)一下在Android中計(jì)時(shí)。然后找本書(shū)救鲤,再深入點(diǎn)學(xué)習(xí)久窟,就自己嘗試一下實(shí)現(xiàn)多線程下載一個(gè)大文件。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末本缠,一起剝皮案震驚了整個(gè)濱河市斥扛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌丹锹,老刑警劉巖犹赖,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異卷仑,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)麸折,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)锡凝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人垢啼,你說(shuō)我怎么就攤上這事窜锯。” “怎么了芭析?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵锚扎,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我馁启,道長(zhǎng)驾孔,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任惯疙,我火速辦了婚禮翠勉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘霉颠。我一直安慰自己对碌,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布蒿偎。 她就那樣靜靜地躺著朽们,像睡著了一般。 火紅的嫁衣襯著肌膚如雪诉位。 梳的紋絲不亂的頭發(fā)上骑脱,一...
    開(kāi)封第一講書(shū)人閱讀 49,821評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音不从,去河邊找鬼惜姐。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的歹袁。 我是一名探鬼主播坷衍,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼条舔!你這毒婦竟也來(lái)了枫耳?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤孟抗,失蹤者是張志新(化名)和其女友劉穎迁杨,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體凄硼,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡铅协,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了摊沉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狐史。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖说墨,靈堂內(nèi)的尸體忽然破棺而出骏全,到底是詐尸還是另有隱情,我是刑警寧澤尼斧,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布姜贡,位于F島的核電站,受9級(jí)特大地震影響棺棵,放射性物質(zhì)發(fā)生泄漏楼咳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一烛恤、第九天 我趴在偏房一處隱蔽的房頂上張望爬橡。 院中可真熱鬧,春花似錦棒动、人聲如沸糙申。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)柜裸。三九已至,卻和暖如春粱锐,著一層夾襖步出監(jiān)牢的瞬間疙挺,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工怜浅, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留铐然,地道東北人蔬崩。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像搀暑,于是被迫代替她去往敵國(guó)和親沥阳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

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