Java 中多線程

1: 概念

進(jìn)程:

進(jìn)程是指在系統(tǒng)中正在運(yùn)行的一個(gè)應(yīng)用程序.每個(gè)進(jìn)程之間是獨(dú)立的,每個(gè)進(jìn)程均運(yùn)行在其專用且受保護(hù)的內(nèi)存空間內(nèi).
例如, 平時(shí)打開的酷狗音樂聽歌, 就是一個(gè)進(jìn)程.

(多)線程:

線程有時(shí)被稱為輕量進(jìn)程(Lightweight Process,LWP),是程序執(zhí)行流的最小單元.
線程是程序中一個(gè)單一的順序控制流程.進(jìn)程內(nèi)有一個(gè)相對(duì)獨(dú)立的门扇、可調(diào)度的執(zhí)行單元,是系統(tǒng)獨(dú)立調(diào)度和分派CPU的基本單位指令運(yùn)行時(shí)的程序的調(diào)度單位.在單個(gè)程序中同時(shí)運(yùn)行多個(gè)線程完成不同的工作,稱為多線程.

進(jìn)程&線程關(guān)系:

進(jìn)程想要執(zhí)行任務(wù),必須有線程(每一個(gè)進(jìn)程至少要有一條線程);
線程是進(jìn)程的執(zhí)行單元,一個(gè)進(jìn)程(程序)的所有任務(wù)都在線程中執(zhí)行.
通常, 線程中的任務(wù)的執(zhí)行都是串行的, 在一個(gè)時(shí)間內(nèi), 一個(gè)線程只能執(zhí)行一個(gè)任務(wù).

為什么要多線程:

可以在一個(gè)進(jìn)程中開啟多條線程, 每條線程可以并行(同行)執(zhí)行不同的任務(wù),充分利用CPU,適當(dāng)?shù)奶岣叱绦虻膱?zhí)行效率.

2: 多線程中常用方法

方法 說明
currentThread 返回當(dāng)前正在執(zhí)行的線程對(duì)象的應(yīng)用
start 使該線程開始執(zhí)行;Java 虛擬機(jī)調(diào)用該線程的 run 方法. 注意, 不要調(diào)用run方法啟動(dòng)線程, 啟動(dòng)線程是start, 如果調(diào)用run方法, 相當(dāng)于在主線程中調(diào)用run方法, 和普通的方法的調(diào)用沒有區(qū)別, 此時(shí)不會(huì)創(chuàng)建一個(gè)新的線程來執(zhí)行定義的任務(wù)
run 如果該線程是使用獨(dú)立的Runnable運(yùn)行對(duì)象構(gòu)造的,則調(diào)用該Runnable對(duì)象的run方法;否則,該方法不執(zhí)行任何操作并返回.
setName 改變線程名稱,使之與參數(shù)name相同.
setPriority 改變線程的優(yōu)先級(jí)
setDeamon 設(shè)置線程為守護(hù)線程或用戶線程
interrupt 中斷線程
isAlive 測試線程是否處于活動(dòng)狀態(tài).
yield 暫停當(dāng)前正在執(zhí)行的線程對(duì)象, 并執(zhí)行其他線程
sleep 讓當(dāng)前正在執(zhí)行的線程休眠指定的毫秒數(shù)

3: 如何創(chuàng)建線程

1: 普通創(chuàng)建 Thread() 對(duì)象
2: 繼承 Thread 類
3: 實(shí)現(xiàn) Runnable 接口
4: 實(shí)現(xiàn) Callable 接口, 實(shí)現(xiàn)Callable接口后, 可以有返回值

4: 實(shí)例講解多線程

例子1(new Thread):

//================Demo1
public class Demo1 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread("thread1");
        thread1.sleep(5000);
        System.out.println("線程名稱: " + thread1.currentThread().getName());

        Thread thread2 = new Thread("thread2");
        thread2.sleep(5000);
        System.out.println("線程名稱: " + thread2.currentThread().getName());
    }
}

//================Demo2
public class Demo2 {
    public static void main(String[] args) {
        Thread thread1 = new Thread("Thread1"){
            public void run() {
                try {
                    Thread.sleep(5000);
                    System.out.println("線程名稱: " + Thread.currentThread().getName());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            };
        };
        thread1.start();

        Thread thread2 = new Thread("Thread2"){
            public void run() {
                try {
                    Thread.sleep(5000);
                    System.out.println("線程名稱: " + Thread.currentThread().getName());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            };
        };
        thread2.start();
    }
}

認(rèn)真體會(huì)一下上面2個(gè)demo, 想一想, 他們執(zhí)行完所花的時(shí)間一樣都是10毫秒嗎?
答案是否定的, Demo1執(zhí)行時(shí)間10毫秒, Demo2執(zhí)行時(shí)間為5毫秒. why?
因?yàn)榈谝粋€(gè)是在同一個(gè)主線程中. 打印的結(jié)果可以看到

Demo1:
線程名稱: main
線程名稱: main

Demo2:
線程名稱: Thread2
線程名稱: Thread1

例子2(extend Thread):

public class Main {
    public static void main(String[] args) {
        for (int i=0; i< 5; i++){
            Thread thread = new MyThread();
            thread.start();
        }
    }
}

public class MyThread extends Thread{
    DateFormat df = new SimpleDateFormat("yyyy年MM月dd日HH時(shí)mm分ss秒S毫秒");

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(df.format( new Date()) + " Thread:" + name + " start.");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(df.format( new Date()) + " Thread:" + name + " end.");
    }
}

===============以下是執(zhí)行結(jié)果
2018年09月25日18時(shí)35分10秒913毫秒 Thread:Thread-0 start.
2018年09月25日18時(shí)35分10秒914毫秒 Thread:Thread-1 start.
2018年09月25日18時(shí)35分10秒915毫秒 Thread:Thread-2 start.
2018年09月25日18時(shí)35分10秒916毫秒 Thread:Thread-3 start.
2018年09月25日18時(shí)35分10秒916毫秒 Thread:Thread-4 start.
2018年09月25日18時(shí)35分15秒914毫秒 Thread:Thread-1 end.
2018年09月25日18時(shí)35分15秒914毫秒 Thread:Thread-0 end.
2018年09月25日18時(shí)35分15秒916毫秒 Thread:Thread-2 end.
2018年09月25日18時(shí)35分15秒916毫秒 Thread:Thread-4 end.
2018年09月25日18時(shí)35分15秒916毫秒 Thread:Thread-3 end.

例子3(實(shí)現(xiàn)Runnable接口):

public class Main {
    public static void main(String[] args) {
        for(int i=0; i<5; i++){
            Thread thread = new Thread(new MyRunnable());
            thread.start();
        }
    }
}

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        DateFormat df = new SimpleDateFormat("yyyy年MM月dd日HH時(shí)mm分ss秒S毫秒");

        System.out.println(df.format(new Date()) + " Thread:" + name + " start.");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(df.format(new Date()) + " Thread:" + name + " end.");
    }
}
//===================結(jié)果, 也是只花了10秒
2018年09月25日18時(shí)41分43秒255毫秒 Thread:Thread-4 start.
2018年09月25日18時(shí)41分43秒255毫秒 Thread:Thread-2 start.
2018年09月25日18時(shí)41分43秒255毫秒 Thread:Thread-0 start.
2018年09月25日18時(shí)41分43秒255毫秒 Thread:Thread-1 start.
2018年09月25日18時(shí)41分43秒260毫秒 Thread:Thread-3 start.
2018年09月25日18時(shí)41分53秒257毫秒 Thread:Thread-4 end.
2018年09月25日18時(shí)41分53秒258毫秒 Thread:Thread-2 end.
2018年09月25日18時(shí)41分53秒258毫秒 Thread:Thread-0 end.
2018年09月25日18時(shí)41分53秒258毫秒 Thread:Thread-1 end.
2018年09月25日18時(shí)41分53秒262毫秒 Thread:Thread-3 end.

例子4(實(shí)現(xiàn)Callable接口):
實(shí)現(xiàn)callable之后, 如果有返回值的話, 就需要放到線程池中, 待全部執(zhí)行完了, 一起返回.

public class Main {
    public static void main(String[] args) {
        int poolsize = 3;
        Date start = new Date();
        List<Future> list = new ArrayList<Future>();

        ExecutorService pool  = Executors.newFixedThreadPool(poolsize);
        for(int i =0; i<poolsize; i++){
            Callable thread = new MyCallable();
            Future result = pool.submit(thread);
            list.add(result);
        }
        pool.shutdown();

        list.forEach(item -> {
            try {
                System.out.println("線程返回值為: " + item.get().toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        Date end = new Date();
        long sec = end.getTime() - start.getTime();
        System.out.println("總共花費(fèi): " + sec + " 毫秒!");
    }
}

public class MyCallable implements Callable {
    @Override
    public Object call() throws Exception {
        DateFormat df = new SimpleDateFormat("yyyy年MM月dd日HH時(shí)mm分ss秒S毫秒");
        String name = Thread.currentThread().getName();

        System.out.println(df.format(new Date()) + " Thread:" + name + " start.");
        Thread.sleep(10000);
        System.out.println(df.format(new Date()) + " Thread:" + name + " end.");

        return name;
    }
}

//===================結(jié)果, 也是只花了10秒
2018年09月25日18時(shí)45分54秒713毫秒 Thread:pool-1-thread-2 start.
2018年09月25日18時(shí)45分54秒716毫秒 Thread:pool-1-thread-3 start.
2018年09月25日18時(shí)45分54秒716毫秒 Thread:pool-1-thread-1 start.
2018年09月25日18時(shí)46分04秒714毫秒 Thread:pool-1-thread-2 end.
2018年09月25日18時(shí)46分04秒717毫秒 Thread:pool-1-thread-3 end.
2018年09月25日18時(shí)46分04秒717毫秒 Thread:pool-1-thread-1 end.
線程返回值為: pool-1-thread-1
線程返回值為: pool-1-thread-2
線程返回值為: pool-1-thread-3
總共花費(fèi): 10051 毫秒!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末梧疲,一起剝皮案震驚了整個(gè)濱河市颠放,隨后出現(xiàn)的幾起案子排惨,更是在濱河造成了極大的恐慌,老刑警劉巖慈迈,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件若贮,死亡現(xiàn)場離奇詭異,居然都是意外死亡痒留,警方通過查閱死者的電腦和手機(jī)谴麦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來伸头,“玉大人匾效,你說我怎么就攤上這事⌒袅祝” “怎么了面哼?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長扫步。 經(jīng)常有香客問我魔策,道長,這世上最難降的妖魔是什么河胎? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任闯袒,我火速辦了婚禮,結(jié)果婚禮上游岳,老公的妹妹穿的比我還像新娘政敢。我一直安慰自己,他們只是感情好胚迫,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布喷户。 她就那樣靜靜地躺著,像睡著了一般访锻。 火紅的嫁衣襯著肌膚如雪褪尝。 梳的紋絲不亂的頭發(fā)上闹获,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音恼五,去河邊找鬼昌罩。 笑死,一個(gè)胖子當(dāng)著我的面吹牛灾馒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播遣总,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼睬罗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了旭斥?” 一聲冷哼從身側(cè)響起容达,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎垂券,沒想到半個(gè)月后花盐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡菇爪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年算芯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凳宙。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡熙揍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出氏涩,到底是詐尸還是另有隱情届囚,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布是尖,位于F島的核電站意系,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏饺汹。R本人自食惡果不足惜蛔添,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望首繁。 院中可真熱鬧作郭,春花似錦、人聲如沸弦疮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽胁塞。三九已至咏尝,卻和暖如春压语,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背编检。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來泰國打工胎食, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人允懂。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓厕怜,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蕾总。 傳聞我的和親對(duì)象是個(gè)殘疾皇子粥航,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

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

  • 進(jìn)程和線程 進(jìn)程 所有運(yùn)行中的任務(wù)通常對(duì)應(yīng)一個(gè)進(jìn)程,當(dāng)一個(gè)程序進(jìn)入內(nèi)存運(yùn)行時(shí),即變成一個(gè)進(jìn)程.進(jìn)程是處于運(yùn)行過程中...
    勝浩_ae28閱讀 5,108評(píng)論 0 23
  • 進(jìn)程和線程 進(jìn)程 所有運(yùn)行中的任務(wù)通常對(duì)應(yīng)一個(gè)進(jìn)程,當(dāng)一個(gè)程序進(jìn)入內(nèi)存運(yùn)行時(shí),即變成一個(gè)進(jìn)程.進(jìn)程是處于運(yùn)行過程中...
    小徐andorid閱讀 2,808評(píng)論 3 53
  • 現(xiàn)在的操作系統(tǒng)是多任務(wù)操作系統(tǒng)。多線程是實(shí)現(xiàn)多任務(wù)的一種方式生百。 進(jìn)程與線程 進(jìn)程是指一個(gè)內(nèi)存中運(yùn)行的應(yīng)用程序递雀,每個(gè)...
    意識(shí)流丶閱讀 641評(píng)論 0 1
  • 單任務(wù) 單任務(wù)的特點(diǎn)是排隊(duì)執(zhí)行,也就是同步蚀浆,就像再cmd輸入一條命令后缀程,必須等待這條命令執(zhí)行完才可以執(zhí)行下一條命令...
    Steven1997閱讀 1,178評(píng)論 0 6
  • cbf95efa8784閱讀 206評(píng)論 0 0