成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java 線程入門

KaltZK / 1849人閱讀

摘要:執(zhí)行新線程的方式是調(diào)用該線程對(duì)象的方法。線程之間沒有父子關(guān)系線程與線程之間是平等的,并沒有父子關(guān)系。線程是并行執(zhí)行的在示例中,其實(shí)是與主線程并行執(zhí)行的。當(dāng)它運(yùn)行完畢時(shí),我們就得到所有線程的執(zhí)行結(jié)果了。

主線程

首先每個(gè) Java 程序都是從主線程開始運(yùn)行的,主線程就是執(zhí)行 main() 方法的那個(gè)線程。在 main() 方法中獲取當(dāng)前線程很簡(jiǎn)單:

// 示例1
public static void main(String[] args) {
    Thread mainThread = Thread.currentThread();
    System.out.println("當(dāng)前線程: " + mainThread.getName());
}

Thread 對(duì)象的文檔在這里。Thread 對(duì)象包含很多方法和屬性,除了上面例子當(dāng)中的 name 屬性外,還有狀態(tài)、優(yōu)先級(jí)等等。現(xiàn)在我們只需要知道 main() 方法是在主線程中運(yùn)行就可以了。

線程是可以暫停的

我們通常使用 sleep() 方法來使線程在指定的時(shí)間內(nèi)暫停執(zhí)行。下面是一個(gè)在主線程中執(zhí)行循環(huán)和暫停的例子:

// 示例2
public static void main(String[] args) {
    for (int i = 0; i < 10; i++) {
        System.out.println(i);

        try {
            Thread.sleep(500);    // 暫停線程
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

注意:首先,sleep() 方法是靜態(tài)的,因?yàn)樗肋h(yuǎn)只能用在當(dāng)前的線程上;其次,sleep() 方法會(huì)拋出異常,該異常通常發(fā)生在暫停狀態(tài)被打斷時(shí)。所以這里用 try-catch 代碼塊包圍起來。

sleep() 方法接受一個(gè) long 類型的參數(shù),指明需要暫停多少毫秒。這個(gè)例子當(dāng)中,我們循環(huán)輸出 i 變量,共循環(huán) 10 次,每輸出一次就暫停 500 毫秒。

你可能覺得整個(gè)程序的運(yùn)行時(shí)間會(huì)是精確的 5000 毫秒,但請(qǐng)千萬不要這么認(rèn)為,首先 sleep() 方法并非十分精確,CPU 在各個(gè)線程之間切換會(huì)要花掉很微量的一點(diǎn)時(shí)間,如果這個(gè)例子循環(huán)次數(shù)不是 10 次而是十萬次百萬次,那么積累的誤差就會(huì)比較大了;其次,代碼中的 System.out.println() 方法和 for 循環(huán)本身也要花掉一點(diǎn)時(shí)間,所以每次循環(huán)不會(huì)是絕對(duì)精確的 500 毫秒。

創(chuàng)建新的線程

除了主線程外,我們還可以創(chuàng)建和執(zhí)行另外的線程。執(zhí)行新線程的方式是調(diào)用該線程對(duì)象的 start() 方法。

// 示例3
public static void main(String[] args) {
    Thread thread1 = new Thread();
    thread1.start();    // 啟動(dòng)線程
}

從這個(gè)例子中我們可以看到,thread1 是一個(gè)通過 new Thread() 創(chuàng)建出來的對(duì)象。把線程看作是對(duì)象這點(diǎn)十分重要,這意味著我們可以創(chuàng)建 Thread 的子類,而子類的對(duì)象仍然是線程對(duì)象。執(zhí)行這段代碼什么輸出都沒有,因?yàn)槲覀儧]有為 thread1 定義要執(zhí)行什么操作。下面的例子中,我們讓 thread1 來做循環(huán)輸出。

// 示例4
public static void main(String[] args) {

    Thread thread1 = new Thread() {

        @Override
        public void run() {               // 指定線程要做的事
            for (int i = 0; i < 10; i++) {
                System.out.println(i);

                try {
                    Thread.sleep(500);    // 暫停線程
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    thread1.start();    // 啟動(dòng)線程
}

這里我們創(chuàng)建了一個(gè) Thread 類的匿名子類,并覆寫了 run() 方法。通過覆寫 run() 方法,我們可以指定線程要做哪些事情。

  

線程之間沒有父子關(guān)系
線程與線程之間是平等的,并沒有父子關(guān)系。不過 Java 為了方便管理線程,定義了一個(gè)叫線程組(ThreadGroup)的類,線程組之間可以存在父子關(guān)系。不過這個(gè)概念平常用的很少,所以這里只是順帶提下,不作詳細(xì)介紹。

線程是并行執(zhí)行的

在示例4中,thread1 其實(shí)是與主線程并行執(zhí)行的。為了演示這點(diǎn),我們首先將這個(gè)循環(huán)提取成一個(gè)方法:

private static void printNumbers(int start, int end) {
    for (int i = start; i < end; i++) {
        System.out.println(i);

        try {
            Thread.sleep(500);    // 暫停線程
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

然后示例4就變成了:

public static void main(String[] args) {

    Thread thread1 = new Thread() {

        @Override
        public void run() {
            printNumbers(0, 10);  // 提取出來的方法
        }
    };

    thread1.start();    // 啟動(dòng)線程
}

我們?cè)谧詈竺嫣砑右恍?,讓主線程在啟動(dòng) thread1 之后也做一個(gè)循環(huán)輸出:

// 示例5
public static void main(String[] args) {

    Thread thread1 = new Thread() {

        @Override
        public void run() {
            printNumbers(0, 10);  // 循環(huán)輸出
        }
    };

    thread1.start();        // 啟動(dòng)線程
    printNumbers(100, 110); // 主線程也循環(huán)輸出
}

執(zhí)行 main() 方法,在輸出中你可以看到 0~9 與 100~109 交替出現(xiàn),這說明主線程和 thread1 在同時(shí)執(zhí)行。

將線程中的邏輯獨(dú)立出來

為了使線程中的邏輯能夠被重用,我們通常將其聲明為一個(gè)獨(dú)立的類。在前面的代碼示例中,我們都是以匿名類的方式來創(chuàng)建線程的。獨(dú)立聲明一個(gè)線程類的方式是這樣的:

// 示例6
public class MyThread extends Thread {

    private int start;
    private int end;

    // 構(gòu)造方法
    public MyThread(int start, int end) {
        this.start = start;
        this.end = end;
    }

    @Override
    public void run() {
        printNumbers();
    }

    private void printNumbers() {
        for (int i = this.start; i < this.end; i++) {
            System.out.println(i);

            try {
                Thread.sleep(500);    // 暫停線程
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在示例 6 中我們可以看到,執(zhí)行這個(gè)線程所需的兩個(gè)參數(shù)現(xiàn)在變成了 MyThread 的兩個(gè)成員。這是我們向線程傳遞執(zhí)行參數(shù)的一般方式。提取成獨(dú)立的類之后,線程使用起來就非常簡(jiǎn)單了:

public static void main(String[] args) {
    new MyThread(0,10).start();
    new MyThread(100,110).start();
    new MyThread(1000,1010).start();
}
線程的返回值

我們有時(shí)候希望當(dāng)線程執(zhí)行完畢時(shí),我們能得到一個(gè)結(jié)果。在示例 6 中我們了解了向線程傳遞參數(shù)的方式,類似的我們也可以為線程類定義一個(gè)成員用來保存線程的執(zhí)行結(jié)果。下面是一個(gè)例子:

// 示例7
public class ThreadWithReturnValue extends Thread {

    public String result;

    @Override
    public void run() {
        try {
            Thread.sleep(3000);
            this.result = "result";  // 假設(shè)產(chǎn)生結(jié)果需要比較長(zhǎng)的時(shí)間
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        ThreadWithReturnValue thread = new ThreadWithReturnValue();
        thread.start();
        Thread.sleep(3100);
        System.out.println(thread.result);  // 獲得結(jié)果
    }
}

在這個(gè)例子當(dāng)中,ThreadWithReturnValue 線程產(chǎn)生結(jié)果需要 3 秒鐘,那么主線程就需要等待 3 秒以上才能得到 "result",否則就只能得到 null。在實(shí)際情況中,我們并不知道線程產(chǎn)生結(jié)果需要多長(zhǎng)時(shí)間,而我們也不想無限制的等下去。

出于這樣的目的,Thread 對(duì)象為我們提供了 join() 方法,用于等待指定的線程直到執(zhí)行完畢。示例 7 當(dāng)中的 main() 方法可以改造成這樣子:

public static void main(String[] args) throws Exception {
    ThreadWithReturnValue thread = new ThreadWithReturnValue();
    thread.start();
    thread.join();      // 等待直到 thread 執(zhí)行完畢
    System.out.println(thread.result);
}

這樣我們就能在線程執(zhí)行完畢時(shí)立刻得到結(jié)果了。我們可以運(yùn)行多個(gè)線程,然后依次調(diào)用它們的 join() 方法,這樣等待的時(shí)間就是它們當(dāng)中運(yùn)行最久的那個(gè)線程的運(yùn)行時(shí)間。當(dāng)它運(yùn)行完畢時(shí),我們就得到所有線程的執(zhí)行結(jié)果了。線程的入門概念就介紹到這里,本文只是介紹非?;镜母拍睿琂ava 在處理多線程和并發(fā)方面還有很多很復(fù)雜的東西等待你去了解和嘗試。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/64182.html

相關(guān)文章

  • Java相關(guān)

    摘要:本文是作者自己對(duì)中線程的狀態(tài)線程間協(xié)作相關(guān)使用的理解與總結(jié),不對(duì)之處,望指出,共勉。當(dāng)中的的數(shù)目而不是已占用的位置數(shù)大于集合番一文通版集合番一文通版垃圾回收機(jī)制講得很透徹,深入淺出。 一小時(shí)搞明白自定義注解 Annotation(注解)就是 Java 提供了一種元程序中的元素關(guān)聯(lián)任何信息和著任何元數(shù)據(jù)(metadata)的途徑和方法。Annotion(注解) 是一個(gè)接口,程序可以通過...

    wangtdgoodluck 評(píng)論0 收藏0
  • Java學(xué)習(xí)路線總結(jié),搬磚工逆襲Java架構(gòu)師(全網(wǎng)最強(qiáng))

    摘要:哪吒社區(qū)技能樹打卡打卡貼函數(shù)式接口簡(jiǎn)介領(lǐng)域優(yōu)質(zhì)創(chuàng)作者哪吒公眾號(hào)作者架構(gòu)師奮斗者掃描主頁(yè)左側(cè)二維碼,加入群聊,一起學(xué)習(xí)一起進(jìn)步歡迎點(diǎn)贊收藏留言前情提要無意間聽到領(lǐng)導(dǎo)們的談話,現(xiàn)在公司的現(xiàn)狀是碼農(nóng)太多,但能獨(dú)立帶隊(duì)的人太少,簡(jiǎn)而言之,不缺干 ? 哪吒社區(qū)Java技能樹打卡?【打卡貼 day2...

    Scorpion 評(píng)論0 收藏0
  • 入門Java線程1

    摘要:一個(gè)線程做完,并將數(shù)據(jù)刷新回主內(nèi)存了,下一個(gè)線程才會(huì)啟動(dòng)。聲明了的變量在被賦值之后,線程會(huì)立刻將值寫回主內(nèi)存在讀取變量時(shí),線程會(huì)到主內(nèi)存去讀取變量的最新值。 一個(gè)例子: public class Counter { public static int count = 0; public synchronized static void inc() { ...

    zhoutao 評(píng)論0 收藏0
  • java&javaweb學(xué)習(xí)筆記(匯總)

    摘要:我的學(xué)習(xí)筆記匯總標(biāo)簽筆記分為兩大部分和筆記內(nèi)容主要是對(duì)一些基礎(chǔ)特性和編程細(xì)節(jié)進(jìn)行總結(jié)整理,適合了解基礎(chǔ)語(yǔ)法,想進(jìn)一步深入學(xué)習(xí)的人如果覺得不錯(cuò),請(qǐng)給,這也是對(duì)我的鼓勵(lì),有什么意見歡迎留言反饋目錄基礎(chǔ)鞏固筆記反射基礎(chǔ)鞏固筆記泛型基礎(chǔ)鞏 我的java&javaweb學(xué)習(xí)筆記(匯總) 標(biāo)簽: java [TOC] 筆記分為兩大部分:javase和javaweb javase javawe...

    yagami 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<