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

資訊專欄INFORMATION COLUMN

Java? 教程(Thread對象)

you_De / 2573人閱讀

Thread對象

每個(gè)線程都與Thread類的實(shí)例相關(guān)聯(lián),使用Thread對象創(chuàng)建并發(fā)應(yīng)用程序有兩種基本策略。

要直接控制線程的創(chuàng)建和管理,只需在每次應(yīng)用程序需要啟動(dòng)異步任務(wù)時(shí)實(shí)例化Thread。

要從應(yīng)用程序的其余部分抽象線程管理,請將應(yīng)用程序的任務(wù)傳遞給執(zhí)行器。

本節(jié)介紹Thread對象的使用,Executors將與其他高級并發(fā)對象一起討論。

定義和啟動(dòng)線程

創(chuàng)建Thread實(shí)例的應(yīng)用程序必須提供將在該線程中運(yùn)行的代碼,有兩種方法可以做到這一點(diǎn):

提供Runnable對象,Runnable接口定義了一個(gè)多帶帶的run方法,用于包含在線程中執(zhí)行的代碼,Runnable對象被傳遞給Thread構(gòu)造函數(shù),如HelloRunnable示例中所示:

public class HelloRunnable implements Runnable {

    public void run() {
        System.out.println("Hello from a thread!");
    }

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

}

子類化Thread,Thread類本身實(shí)現(xiàn)了Runnable,盡管它的run方法什么都不做,應(yīng)用程序可以子類化Thread,提供自己的run實(shí)現(xiàn),如HelloThread示例中所示:

public class HelloThread extends Thread {

    public void run() {
        System.out.println("Hello from a thread!");
    }

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

}

請注意,兩個(gè)示例都調(diào)用Thread.start以啟動(dòng)新線程。

你應(yīng)該使用哪個(gè)語法?使用Runnable對象的第一個(gè)語法更通用,因?yàn)?b>Runnable對象可以繼承Thread以外的類。第二個(gè)語法在簡單的應(yīng)用程序中更容易使用,但受限于你的任務(wù)類必須是Thread的后代這一事實(shí)。本課重點(diǎn)介紹第一種方法,該方法將Runnable任務(wù)與執(zhí)行任務(wù)的Thread對象分開,這種方法不僅更靈活,而且適用于后面介紹的高級線程管理API。

Thread類定義了許多對線程管理有用的方法,這些包括靜態(tài)方法,它們提供關(guān)于調(diào)用該方法的線程的信息,或影響該線程的狀態(tài)。其他方法是從管理線程和Thread對象的其他線程調(diào)用的,我們將在以下部分中研究其中一些方法。

用Sleep暫停執(zhí)行

Thread.sleep導(dǎo)致當(dāng)前線程暫停執(zhí)行指定的時(shí)間段,這是使處理器時(shí)間可用于應(yīng)用程序的其他線程或可能在計(jì)算機(jī)系統(tǒng)上運(yùn)行的其他應(yīng)用程序的有效方法。sleep方法也可以用于調(diào)步,如下面的示例所示,和等待具有被理解為具有時(shí)間要求的職責(zé)的另一個(gè)線程,如稍后部分中的SimpleThreads示例。

提供了兩個(gè)重載版本的sleep:一個(gè)指定毫秒的睡眠時(shí)間,一個(gè)指定納秒的睡眠時(shí)間。但是,這些睡眠時(shí)間并不能保證精確,因?yàn)樗鼈兪艿降讓硬僮飨到y(tǒng)提供的設(shè)施的限制,此外,睡眠周期可以通過中斷終止,我們將在后面的部分中看到。在任何情況下,你都不能設(shè)想調(diào)用sleep會準(zhǔn)確地在指定的時(shí)間段內(nèi)暫停該線程。

SleepMessages示例使用sleep以四秒為間隔打印消息:

public class SleepMessages {
    public static void main(String args[])
        throws InterruptedException {
        String importantInfo[] = {
            "Mares eat oats",
            "Does eat oats",
            "Little lambs eat ivy",
            "A kid will eat ivy too"
        };

        for (int i = 0;
             i < importantInfo.length;
             i++) {
            //Pause for 4 seconds
            Thread.sleep(4000);
            //Print a message
            System.out.println(importantInfo[i]);
        }
    }
}

請注意,main聲明拋出InterruptedException,這是一個(gè)異常,當(dāng)sleep處于活動(dòng)狀態(tài)時(shí),另一個(gè)線程中斷當(dāng)前線程時(shí),sleep將拋出,由于此應(yīng)用程序尚未定義另一個(gè)導(dǎo)致中斷的線程,因此無需捕獲InterruptedException。

中斷

中斷是指示線程應(yīng)該停止正在做的事情,并執(zhí)行其他操作,由程序員決定線程如何響應(yīng)中斷,但用于終止線程是很常見的,這是本課程中強(qiáng)調(diào)的用法。

線程通過調(diào)用Thread對象上的interrupt來發(fā)送中斷,以便線程被中斷,為使中斷機(jī)制正常工作,被中斷的線程必須支持自己的中斷。

支持中斷

線程如何支持自己的中斷?這取決于它目前正在做什么,如果線程經(jīng)常調(diào)用拋出InterruptedException的方法,它只會在捕獲該異常后從run方法返回。例如,假設(shè)SleepMessages示例中的中心消息循環(huán)位于線程的Runnable對象的run方法中,然后可以按如下方式修改它以支持中斷:

for (int i = 0; i < importantInfo.length; i++) {
    // Pause for 4 seconds
    try {
        Thread.sleep(4000);
    } catch (InterruptedException e) {
        // We"ve been interrupted: no more messages.
        return;
    }
    // Print a message
    System.out.println(importantInfo[i]);
}

許多拋出InterruptedException的方法(例如sleep)被設(shè)計(jì)為收到中斷時(shí)取消當(dāng)前操作并立即返回。

如果一個(gè)線程長時(shí)間運(yùn)行而不調(diào)用拋出InterruptedException的方法呢?那么它必須定期調(diào)用Thread.interrupted,如果收到中斷,則返回true,例如:

for (int i = 0; i < inputs.length; i++) {
    heavyCrunch(inputs[i]);
    if (Thread.interrupted()) {
        // We"ve been interrupted: no more crunching.
        return;
    }
}

在這個(gè)簡單的例子中,代碼只是測試中斷,如果收到中斷則退出線程,在更復(fù)雜的應(yīng)用程序中,拋出InterruptedException可能更有意義:

if (Thread.interrupted()) {
    throw new InterruptedException();
}

這允許中斷處理代碼集中在catch子句中。

中斷狀態(tài)標(biāo)志

中斷機(jī)制使用稱為中斷狀態(tài)的內(nèi)部標(biāo)志來實(shí)現(xiàn),調(diào)用Thread.interrupt設(shè)置此標(biāo)志,當(dāng)線程通過調(diào)用靜態(tài)方法Thread.interrupted來檢查中斷時(shí),將清除中斷狀態(tài),非靜態(tài)isInterrupted方法,由一個(gè)線程用于查詢另一個(gè)線程的中斷狀態(tài),不會更改中斷狀態(tài)標(biāo)志。

按照慣例,任何通過拋出InterruptedException退出的方法都會在執(zhí)行此操作時(shí)清除中斷狀態(tài),但是,通過另一個(gè)線程調(diào)用中斷,總是可以立即再次設(shè)置中斷狀態(tài)。

加入

join方法允許一個(gè)線程等待另一個(gè)線程的完成,如果t是其線程當(dāng)前正在執(zhí)行的Thread對象:

t.join();

導(dǎo)致當(dāng)前線程暫停執(zhí)行,直到t的線程終止,join重載方法允許程序員指定等待周期,但是,與sleep一樣,join依賴于OS進(jìn)行計(jì)時(shí),因此你不應(yīng)該設(shè)想join將準(zhǔn)確地等待你指定的時(shí)間。

sleep一樣,join通過InterruptedException退出來響應(yīng)中斷。

SimpleThreads示例

以下示例匯總了本節(jié)的一些概念,SimpleThreads由兩個(gè)線程組成。第一個(gè)是每個(gè)Java應(yīng)用程序都有的主線程,主線程從Runnable對象MessageLoop創(chuàng)建一個(gè)新線程,并等待它完成,如果MessageLoop線程需要很長時(shí)間才能完成,主線程會中斷它。

MessageLoop線程打印出一系列消息,如果在打印完所有消息之前被中斷,MessageLoop線程將打印一條消息并退出。

public class SimpleThreads {

    // Display a message, preceded by
    // the name of the current thread
    static void threadMessage(String message) {
        String threadName =
            Thread.currentThread().getName();
        System.out.format("%s: %s%n",
                          threadName,
                          message);
    }

    private static class MessageLoop
        implements Runnable {
        public void run() {
            String importantInfo[] = {
                "Mares eat oats",
                "Does eat oats",
                "Little lambs eat ivy",
                "A kid will eat ivy too"
            };
            try {
                for (int i = 0;
                     i < importantInfo.length;
                     i++) {
                    // Pause for 4 seconds
                    Thread.sleep(4000);
                    // Print a message
                    threadMessage(importantInfo[i]);
                }
            } catch (InterruptedException e) {
                threadMessage("I wasn"t done!");
            }
        }
    }

    public static void main(String args[])
        throws InterruptedException {

        // Delay, in milliseconds before
        // we interrupt MessageLoop
        // thread (default one hour).
        long patience = 1000 * 60 * 60;

        // If command line argument
        // present, gives patience
        // in seconds.
        if (args.length > 0) {
            try {
                patience = Long.parseLong(args[0]) * 1000;
            } catch (NumberFormatException e) {
                System.err.println("Argument must be an integer.");
                System.exit(1);
            }
        }

        threadMessage("Starting MessageLoop thread");
        long startTime = System.currentTimeMillis();
        Thread t = new Thread(new MessageLoop());
        t.start();

        threadMessage("Waiting for MessageLoop thread to finish");
        // loop until MessageLoop
        // thread exits
        while (t.isAlive()) {
            threadMessage("Still waiting...");
            // Wait maximum of 1 second
            // for MessageLoop thread
            // to finish.
            t.join(1000);
            if (((System.currentTimeMillis() - startTime) > patience)
                  && t.isAlive()) {
                threadMessage("Tired of waiting!");
                t.interrupt();
                // Shouldn"t be long now
                // -- wait indefinitely
                t.join();
            }
        }
        threadMessage("Finally!");
    }
}
上一篇:進(jìn)程和線程 下一篇:同步

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

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

相關(guān)文章

  • [譯] Java 8 Nashorn 教程

    摘要:未來的主要發(fā)布基于。在中調(diào)用函數(shù)支持從代碼中直接調(diào)用定義在腳本文件中的函數(shù)。下面的函數(shù)稍后會在端調(diào)用為了調(diào)用函數(shù),你首先需要將腳本引擎轉(zhuǎn)換為。調(diào)用函數(shù)將結(jié)果輸出到,所以我們會首先看到輸出。幸運(yùn)的是,有一套補(bǔ)救措施。 原文:Java 8 Nashorn Tutorial 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 這個(gè)教程中,你會通過簡單易懂的代碼示例,來了解Nashorn Ja...

    _ivan 評論0 收藏0
  • Java 8 并發(fā)教程:線程和執(zhí)行器

    摘要:在這個(gè)示例中我們使用了一個(gè)單線程線程池的。在延遲消逝后,任務(wù)將會并發(fā)執(zhí)行。這是并發(fā)系列教程的第一部分。第一部分線程和執(zhí)行器第二部分同步和鎖第三部分原子操作和 Java 8 并發(fā)教程:線程和執(zhí)行器 原文:Java 8 Concurrency Tutorial: Threads and Executors 譯者:BlankKelly 來源:Java8并發(fā)教程:Threads和Execut...

    jsdt 評論0 收藏0
  • Java? 教程(Lock對象

    Lock對象 同步代碼依賴于簡單的可重入鎖,這種鎖易于使用,但有許多限制,java.util.concurrent.locks包支持更復(fù)雜的鎖定語法,我們不會詳細(xì)檢查這個(gè)包,而是將重點(diǎn)放在其最基本的接口Lock上。 Lock對象的工作方式與同步代碼使用的隱式鎖定非常相似,與隱式鎖一樣,一次只有一個(gè)線程可以擁有一個(gè)Lock對象,Lock對象還通過其關(guān)聯(lián)的Condition對象支持wait/notif...

    RobinQu 評論0 收藏0
  • Java精講:生產(chǎn)者-消費(fèi)者

    摘要:創(chuàng)建一個(gè)阻塞隊(duì)列生產(chǎn)者生產(chǎn),目前總共有消費(fèi)者消費(fèi),目前總共有原文鏈接更多教程 原文鏈接 更多教程 本文概要 生產(chǎn)者和消費(fèi)者問題是線程模型中老生常談的問題,也是面試中經(jīng)常遇到的問題。光在Java中的實(shí)現(xiàn)方式多達(dá)數(shù)十種,更不用說加上其他語言的實(shí)現(xiàn)方式了。那么我們該如何學(xué)習(xí)呢? 本文會通過精講wait()和notify()方法實(shí)現(xiàn)生產(chǎn)者-消費(fèi)者模型,來學(xué)習(xí)生產(chǎn)者和消費(fèi)者問題的原理。 目的...

    VPointer 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<