線程的創(chuàng)建與使用(一)

多線程,一個(gè)讓我學(xué)生時(shí)代感覺逼格較高的詞語之一,因?yàn)槁牪欢.?dāng)時(shí)聽java多線程這部分課程時(shí),已忘記我在干嘛,反正沒聽課。只記得有次在機(jī)房上機(jī),一男同學(xué)好像在看電視劇《老公的春天》,還被老師逮住了,哈哈哈。俗話說“躲得過初一,躲不過十五”,欠下的終歸要還的......


線程&多線程

線程的意義,在上篇中就有提到,它作為操作系統(tǒng)調(diào)度的最小單元,多個(gè)線程能一塊執(zhí)行,提升性能,尤其在多處理器中,就不再多說了。

線程的創(chuàng)建與啟動(dòng)

線程的啟動(dòng)基本有三種方式:①繼承Thread,重寫run()方法 ②實(shí)現(xiàn)Runnable接口,重寫run()方法 ③創(chuàng)建FutureTask對象,創(chuàng)建Callable子類對象,重寫call()方法。這篇先介紹下前兩種,因?yàn)樗鼉蛇\(yùn)行完run()完沒有返回值,而第三種是有返回值的:

繼承Thread
public class Test1 extends Thread {
    @Override
    public void run() {
        for(int i = 0; i < 10; i++){
            System.out.println("當(dāng)前線程名為:"+Thread.currentThread().getName() + "***哈哈哈***:" + i);
        }
    }
    public static void main(String[] args) {
        Test1 thread1 = new Test1();
        thread1.start();
    }
}

執(zhí)行結(jié)果如下:

單線程

這是一個(gè)最簡單的線程使用,只創(chuàng)建了一個(gè)線程對象,還是單線程,再創(chuàng)建一個(gè)thread2,就是多線程了。修改上面的的main函數(shù):

public static void main(String[] args) {
        Test1 thread1 = new Test1();
        Test1 thread2 = new Test1();
        thread1.start();
        thread2.start();
}

結(jié)果如下:

多線程

啟動(dòng)線程的方式就是執(zhí)行Thread的start()方法,strat()方法是一個(gè)native方法,它將啟動(dòng)一個(gè)新線程,并執(zhí)行run()方法,可以瞅瞅它的實(shí)現(xiàn):

public synchronized void start() {
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
        group.add(this);
        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
            }
        }
    }

    private native void start0();

如果一個(gè)線程對象執(zhí)行run()方法,不執(zhí)行start()方法,結(jié)果是怎樣的?繼續(xù)拿第一個(gè)單線程來試驗(yàn):

public static void main(String[] args) {
        Test1 thread1 = new Test1();
        thread1.run();
}

結(jié)果和thread.start()一模一樣,因?yàn)門hread也是Runnable的實(shí)現(xiàn)類。



那么如果一個(gè)線程對象多次調(diào)用start()方法和run()方法的情況是怎樣的?來,接著試:

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

結(jié)果報(bào)錯(cuò):

在Thread的start()方法處打斷點(diǎn),可以看到thread1對象第一次執(zhí)行start()方法時(shí),threadStatus=0,成功執(zhí)行;當(dāng)thread1第二次執(zhí)行start()方法時(shí),threadStatus=2(這個(gè)狀態(tài)值并不是固定的,但都非零),拋出了異常,說明了同一個(gè)線程對象不能多次執(zhí)行start()方法。

第一次執(zhí)行start()

第二次執(zhí)行start()

接著咱們看一個(gè)線程對象多次執(zhí)行run()方法:

public static void main(String[] args) {
        Test1 thread1 = new Test1();
        thread1.run();
        thread1.run();
}

執(zhí)行結(jié)果:


可以看到,這時(shí)候并沒有開啟新的線程,main線程直接調(diào)用執(zhí)行了run()方法中代碼。所以,start()會(huì)開啟新的線程并在新線程中執(zhí)行run()方法,而run()方法不會(huì)開啟新線程。

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

public class Test2 implements Runnable {
    @Override
    public void run() {
        for(int i =0; i < 10; i++){
            System.out.println("當(dāng)前線程名為:"+Thread.currentThread().getName() + "***哈哈哈***:" + i);
        }
    }
    public static void main(String[] args) {
        Test2 test2 = new Test2();
        Thread thread1 = new Thread(test2);
        thread1.start();
    }
}

執(zhí)行結(jié)果:


這個(gè)也是單線程,為了啟動(dòng)線程,先創(chuàng)建一個(gè)Thread實(shí)例,再將Test2實(shí)例傳入,在Thread所實(shí)現(xiàn)的run()方法處打斷點(diǎn),可以看見Thread的run()方法就會(huì)調(diào)用target.run()。


小結(jié)

此篇主要介紹了兩種無返回結(jié)果的線程創(chuàng)建方式。兩種方式的區(qū)別如下:①繼承Thread這種不是很靈活,因Java的單一繼承性,繼承了Thread就別再妄想繼承別的類了;②實(shí)現(xiàn)Runnable接口這種方式就巧妙地避開了這個(gè)弊端,更加符合面向?qū)ο蟮木幊谭绞?,也降低了線程對象和線程任務(wù)的耦合性。總之,建議使用第二種實(shí)現(xiàn)Runnable的方式來創(chuàng)建線程。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文主要講了java中多線程的使用方法、線程同步、線程數(shù)據(jù)傳遞、線程狀態(tài)及相應(yīng)的一些線程函數(shù)用法、概述等。 首先講...
    李欣陽閱讀 2,597評(píng)論 1 15
  • Java多線程學(xué)習(xí) [-] 一擴(kuò)展javalangThread類 二實(shí)現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 3,108評(píng)論 1 18
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,692評(píng)論 18 399
  • 前言 多線程并發(fā)編程是Java編程中重要的一塊內(nèi)容,也是面試重點(diǎn)覆蓋區(qū)域,所以學(xué)好多線程并發(fā)編程對我們來說極其重要...
    嘟爺MD閱讀 7,413評(píng)論 21 272
  • 能進(jìn)去這么一個(gè)社群和大家一同學(xué)習(xí)進(jìn)步是一件美好的事情,感覺到路上不那么孤單,而且看著大家睿智的發(fā)言,碰撞出了思想交...
    Toradola閱讀 267評(píng)論 0 1

友情鏈接更多精彩內(nèi)容