Java基礎(chǔ)之線程

學(xué)Java的應(yīng)該都知道怕磨,不同于其他大多數(shù)編程語言演痒,Java本身內(nèi)置了多線程的支持始花。多線程讓許多任務(wù)可以同時進(jìn)行妄讯,提高了程序的運(yùn)行效率,帶來了許多便利酷宵,但是許多情況下多線程并不會按照我們所計(jì)劃的進(jìn)行亥贸,也就成了許多程序員的噩夢。那么今天浇垦,我們就來聊聊Java中的線程相關(guān)的內(nèi)容炕置。
本文的要點(diǎn)如下:

  • Java線程的基本概念
    • 任務(wù)
    • Thread類
    • 執(zhí)行任務(wù)
  • 線程的基本方法

Java線程的基本概念

說到線程男韧,那么就不得不提到另一個常用的概念——線程朴摊。線程和進(jìn)程,總有人傻傻的分不清此虑。
線程是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位甚纲。而進(jìn)程則是系統(tǒng)進(jìn)行資源分配和調(diào)度的基本單位。簡而言之進(jìn)程就是我們常說的一個應(yīng)用程序朦前,而進(jìn)程中可以包含多個線程分別進(jìn)行不同的工作介杆。

任務(wù)

任務(wù)就是線程中要執(zhí)行的動作。
在Java中的任務(wù)被抽象成了一個Runnable接口:

public interface Runnable {
    public void run();
}

我們的自定義任務(wù)需要去實(shí)現(xiàn)這個接口况既,并把任務(wù)的詳細(xì)內(nèi)容寫在覆蓋的run方法里这溅,比如我們定義一個輸出一個字符串的任務(wù):

public class PrintTask implements Runnable {
    @Override
    public void run() {
        System.out.println("輸出一行字");
    }
}

Thread類

Java中用Thread類來代表一個線程,而我們常用的是它的這幾種構(gòu)造方法:

Thread(Runnable target, String name)

在創(chuàng)建線程對象的時候傳入需要執(zhí)行的任務(wù)以及這個線程的名稱棒仍。

Thread(Runnable target)

只傳入需要執(zhí)行的任務(wù),名稱是系統(tǒng)自動生成的臭胜,或者可以在創(chuàng)建對象后再通過setName方法修改名稱莫其。

Thread(String name)

只傳入待創(chuàng)建線程的名稱。

Thread()

啥都不傳耸三,就是單純構(gòu)造一個線程對象而已~

執(zhí)行任務(wù)

Thread類的start()方法負(fù)責(zé)開始執(zhí)行一個線程乱陡,讓一個線程運(yùn)行起來有這么兩種方法:

1、創(chuàng)建Thread對象的時候指定需要執(zhí)行的任務(wù):

public class Test {

    public static void main(String[] args) {
        new Thread(new PrintTask()).start();
    }
}

2仪壮、通過繼承Thread類并覆蓋run方法:

Thread類本身就代表了一個Runnable任務(wù)憨颠,我們看Thread類的定義:

public class Thread implements Runnable {

    private Runnable target;

    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

    // ... 為省略篇幅,省略其他方法和字段
}

其中的target就是在構(gòu)造方法里傳入的,如果構(gòu)造方法不傳這個字段的話爽彤,很顯然run方法就是一個空實(shí)現(xiàn)养盗,所以如果我們想運(yùn)行這個線程,就繼承它并且覆蓋一下run方法适篙。

public class PrintThread extends Thread {

    @Override
    public void run() {
        System.out.println("輸出一行字");
    }
}

因?yàn)镻rintThread中已經(jīng)有一個任務(wù)了往核,所以直接調(diào)用start方法運(yùn)行它就好:

public class Test {

    public static void main(String[] args) {
        new PrintThread().start();
    }
}

使用繼承Thread類并且覆蓋run方法的方式把線程和任務(wù)給結(jié)合到了一塊兒了,不可分割了嚷节,也就是所謂的耦合了聂儒,現(xiàn)在都流行低耦合的方式,為了便于修改嘛硫痰。所以我們平時更傾向于使用任務(wù)和線程分開處理的第1種執(zhí)行任務(wù)的方式衩婚。當(dāng)然,有時候?yàn)榱搜菔镜姆奖阈О撸彩菚褂美^承Thread類并且覆蓋run方法的方式非春。

線程基本方法

Thread類提供了許多方法來方便我們獲取線程的信息或者控制線程,下邊來一下都有哪些重要的方法吧:

1.獲取線程ID

long getId():系統(tǒng)會為每個線程自動分配一個long類型的id值鳍悠,通過getId方法可以獲取這個值税娜。

2.獲取和設(shè)置線程名稱

  • void setName(String name):設(shè)置線程的名稱。
  • String getName():獲取線程的名稱藏研。

3.獲取和設(shè)置線程優(yōu)先級

處理器會從就緒隊(duì)列里挑一個已經(jīng)就緒的線程去執(zhí)行敬矩,每個線程都可以有不同的優(yōu)先級,優(yōu)先級越高蠢挡,越容易被處理器選中去執(zhí)行弧岳。
void setPriority(int newPriority):設(shè)置線程優(yōu)先級。

java中的優(yōu)先級是用一個正數(shù)表示业踏,共有1~10十個等級禽炬,其中,設(shè)計(jì)java的大叔們用了三個靜態(tài)變量表示我們常用的:

  • Thread.MIN_PRIORITY = 1
  • Thread.NORM_PRIORITY = 5;
  • Thread.MAX_PRIORITY = 10;

一般情況下勤家,我們就用這三個變量去表示優(yōu)先級就夠用了~

int getPriority():獲取線程的優(yōu)先級腹尖。

4.休眠

如果想在線程執(zhí)行過程中讓程序停一段時間之后再執(zhí)行,這個停止一段時間也叫做休眠伐脖,就好像睡一段時間然后再醒來热幔。可以通過調(diào)用sleep方法讼庇,來實(shí)現(xiàn)休眠:

static void sleep(long millis) throws InterruptedException

程序在指定的毫秒數(shù)內(nèi)讓當(dāng)前正在執(zhí)行的線程休眠绎巨,也就是暫停執(zhí)行。

static void sleep(long millis, int nanos) throws InterruptedException

程序在指定的毫秒數(shù)加納秒數(shù)內(nèi)讓當(dāng)前正在執(zhí)行的線程休眠蠕啄,也就是暫停執(zhí)行场勤。

這個sleep方法是一個靜態(tài)方法,它會讓當(dāng)前線程暫停指定的時間。這個所謂的暫停和媳,或者說休眠其實(shí)只是把正在運(yùn)行的線程阻塞掉格遭,放到阻塞隊(duì)列里,等指定的時間一到窗价,再從阻塞隊(duì)列里出來而已如庭。

5.獲取當(dāng)前正在執(zhí)行的線程

不同的線程可以共享同一個進(jìn)程中的同一段內(nèi)存,也就意味著不同的線程可以執(zhí)行同一段代碼撼港,有些時候有必要獲取一下代碼在哪個線程中執(zhí)行坪它。

static Thread currentThread():獲取當(dāng)前正在執(zhí)行的線程對象的引用。

6.守護(hù)線程

線程可以被分成兩種類型帝牡,一種叫普通線程往毡,另一種就叫守護(hù)線程,守護(hù)線程也被稱為后臺線程靶溜。守護(hù)線程在程序執(zhí)行過程中并不是不可或缺的开瞭,它主要是為普通線程提供便利服務(wù)的,比方說java中不需要我們手動去釋放某個對象的內(nèi)存罩息,它有一種傳說中的垃圾收集器在不停的去釋放程序中不需要的內(nèi)存嗤详,在我們啟動程序的時候系統(tǒng)會幫助我們創(chuàng)建一個負(fù)責(zé)收集垃圾的線程,這個線程就是一個守護(hù)線程瓷炮。如果所有的普通線程全部死掉了葱色,那守護(hù)線程也會跟著死掉,也就是程序就退出了娘香,比方說在所有的普通線程停止了之后苍狰,這個負(fù)責(zé)收集垃圾的守護(hù)線程也會自動退出的。反過來說只要有一個普通線程活著烘绽,程序就不會退出淋昭。我們可以通過下邊這些方法來判斷一個線程是否是守護(hù)線程或者把一個線程設(shè)置為守護(hù)線程:

  • boolean isDaemon():判斷該線程是否為守護(hù)線程。
  • void setDaemon(boolean on):將該線程標(biāo)記為守護(hù)線程或者普通線程安接。

只有在線程未啟動的時候才能設(shè)置該線程是否為守護(hù)線程翔忽,否則的話會拋出異常。
另外盏檐,從普通線程中生成的線程默認(rèn)是普通線程呀打,從守護(hù)線程中生成的線程默認(rèn)是守護(hù)線程

7.讓出本次處理器時間片

static void yield():表示放棄此次時間片時間糯笙,等待下次執(zhí)行。
但是撩银,這個yield方法只是建議處理器不要在此次時間片時間內(nèi)繼續(xù)執(zhí)行本線程给涕,最后實(shí)際怎么著還不一定呢,另外,yield是一個靜態(tài)方法够庙,表示讓出當(dāng)前線程本次時間片的時間恭应。

8.等待另一線程執(zhí)行結(jié)束

有的時候需要等待一個線程執(zhí)行完了,另一個線程才能繼續(xù)執(zhí)行耘眨,Thread類提供了這樣的方法:

void join()

等待該線程終止才能繼續(xù)執(zhí)行昼榛。

void join(long millis)

在指定毫秒數(shù)內(nèi)等待該線程終止,如果到達(dá)了指定時間就繼續(xù)之行了剔难。

void join(long millis, int nanos)

跟上邊方法一個意思胆屿,只不過加了個納秒限制。

總結(jié)一下:

  1. 當(dāng)我們運(yùn)行一個java程序時偶宫,系統(tǒng)會為我們默認(rèn)創(chuàng)建一個名叫main的線程非迹。
  2. java中的任務(wù)被抽象成了一個Runnable接口,我們的自定義任務(wù)需要去實(shí)現(xiàn)這個接口纯趋,并把任務(wù)的詳細(xì)內(nèi)容寫在覆蓋的run方法里憎兽。
  3. java中的Thread類來代表一個線程,它提供設(shè)置線程名吵冒、線程要執(zhí)行的任務(wù)等相關(guān)構(gòu)造方法纯命。
  4. 調(diào)用Thread對象的start方法可以執(zhí)行一個線程,使用某個線程執(zhí)行某個任務(wù)的方式有兩種:
    • 創(chuàng)建Thread對象的時候指定需要執(zhí)行的任務(wù)痹栖。
    • 通過繼承Thread類并覆蓋run方法亿汞。
  5. Thread類提供一系列方法來方便我們獲取線程的信息或者控制線程,包括下邊這些功能:
    • 獲取線程ID
    • 獲取和設(shè)置線程名稱
    • 獲取和設(shè)置線程優(yōu)先級
    • 線程休眠
    • 獲取當(dāng)前正在執(zhí)行的線程
    • 守護(hù)線程的設(shè)置和判斷相關(guān)方法
    • 讓出本次處理器時間片
    • 等待另一線程執(zhí)行結(jié)束
  6. 可以為某個線程設(shè)置異常處理器來捕獲線程中沒有catch的異常结耀。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末留夜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子图甜,更是在濱河造成了極大的恐慌碍粥,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件黑毅,死亡現(xiàn)場離奇詭異嚼摩,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)矿瘦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進(jìn)店門枕面,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人缚去,你說我怎么就攤上這事潮秘。” “怎么了易结?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵枕荞,是天一觀的道長柜候。 經(jīng)常有香客問我,道長躏精,這世上最難降的妖魔是什么渣刷? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮矗烛,結(jié)果婚禮上辅柴,老公的妹妹穿的比我還像新娘。我一直安慰自己瞭吃,他們只是感情好碌嘀,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著虱而,像睡著了一般筏餐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上牡拇,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天魁瞪,我揣著相機(jī)與錄音,去河邊找鬼惠呼。 笑死导俘,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的剔蹋。 我是一名探鬼主播旅薄,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼泣崩!你這毒婦竟也來了少梁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤矫付,失蹤者是張志新(化名)和其女友劉穎凯沪,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體买优,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡妨马,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了杀赢。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片烘跺。...
    茶點(diǎn)故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖脂崔,靈堂內(nèi)的尸體忽然破棺而出滤淳,到底是詐尸還是另有隱情,我是刑警寧澤砌左,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布娇钱,位于F島的核電站伤柄,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏文搂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一秤朗、第九天 我趴在偏房一處隱蔽的房頂上張望煤蹭。 院中可真熱鬧,春花似錦取视、人聲如沸硝皂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽稽物。三九已至,卻和暖如春折欠,著一層夾襖步出監(jiān)牢的瞬間贝或,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工锐秦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留咪奖,地道東北人。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓酱床,卻偏偏與公主長得像羊赵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子扇谣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評論 2 348

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

  • 一昧捷、線程分類 二、線程的實(shí)現(xiàn)方式 三罐寨、線程的狀態(tài) 四靡挥、線程的核心方法 sleep()方法:該方法屬于Thread類...
    M_JCs閱讀 266評論 0 1
  • Java多線程學(xué)習(xí) [-] 一擴(kuò)展javalangThread類 二實(shí)現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 2,952評論 1 18
  • 寫在前面的話: 這篇博客是我從這里“轉(zhuǎn)載”的,為什么轉(zhuǎn)載兩個字加“”呢衩茸?因?yàn)檫@絕不是簡單的復(fù)制粘貼芹血,我花了五六個小...
    SmartSean閱讀 4,717評論 12 45
  • 本文主要講了java中多線程的使用方法、線程同步楞慈、線程數(shù)據(jù)傳遞幔烛、線程狀態(tài)及相應(yīng)的一些線程函數(shù)用法、概述等囊蓝。 首先講...
    李欣陽閱讀 2,444評論 1 15
  • 數(shù)據(jù)庫主從熱備 數(shù)據(jù)庫安裝 1.安裝yum源 打開https://yum.postgresql.org/repop...
    384c7feea940閱讀 2,036評論 0 3