溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

java線程的作用是什么

發(fā)布時間:2020-10-23 16:49:25 來源:億速云 閱讀:141 作者:小新 欄目:編程語言

java線程的作用是什么?這個問題可能是我們?nèi)粘W(xué)習(xí)或工作經(jīng)常見到的。希望通過這個問題能讓你收獲頗深。下面是小編給大家?guī)淼膮⒖純?nèi)容,讓我們一起來看看吧!

什么是線程?

幾乎每種操作系統(tǒng)都支持進程的概念-- 進程就是在某種程度上相互隔離的、獨立運行的程序。

線程化是允許多個活動共存于一個進程中的工具。大多數(shù)現(xiàn)代的操作系統(tǒng)都支持線程,而且線程的概念以各種形式已存在了好多年。Java 是第一個在語言本身中顯式地包含線程的主流編程語言,它沒有把線程化看作是底層操作系統(tǒng)的工具。

有時候,線程也稱作輕量級進程。就象進程一樣,線程在程序中是獨立的、并發(fā)的執(zhí)行路徑,每個線程有它自己的堆棧、自己的程序計數(shù)器和自己的局部變量。但是,與分隔的進程相比,進程中的線程之間的隔離程度要小。它們共享內(nèi)存、文件句柄和其它每個進程應(yīng)有的狀態(tài)。

進程可以支持多個線程,它們看似同時執(zhí)行,但互相之間并不同步。一個進程中的多個線程共享相同的內(nèi)存地址空間,這就意味著它們可以訪問相同的變量和對象,而且它們從同一堆中分配對象。盡管這讓線程之間共享信息變得更容易,但您必須小心,確保它們不會妨礙同一進程里的其它線程。

Java 線程工具和 API 看似簡單。但是,編寫有效使用線程的復(fù)雜程序并不十分容易。因為有多個線程共存在相同的內(nèi)存空間中并共享相同的變量,所以您必須小心,確保您的線程不會互相干擾。

每個 Java 程序都使用線程

每個 Java 程序都至少有一個線程 ― 主線程。當(dāng)一個 Java 程序啟動時,JVM 會創(chuàng)建主線程,并在該線程中調(diào)用程序的 main() 方法。

JVM 還創(chuàng)建了其它線程,您通常都看不到它們 ― 例如,與垃圾收集、對象終止和其它 JVM 內(nèi)務(wù)處理任務(wù)相關(guān)的線程。其它工具也創(chuàng)建線程,如 AWT(抽象窗口工具箱(Abstract Windowing Toolkit))或 Swing UI 工具箱、servlet 容器、應(yīng)用程序服務(wù)器和 RMI(遠(yuǎn)程方法調(diào)用(Remote Method Invocation))。

為什么使用線程?

在 Java 程序中使用線程有許多原因。如果您使用 Swing、servlet、RMI 或 Enterprise JavaBeans(EJB)技術(shù),您也許沒有意識到您已經(jīng)在使用線程了。

使用線程的一些原因是它們可以幫助:

使 UI 響應(yīng)更快

利用多處理器系統(tǒng)

簡化建模

執(zhí)行異步或后臺處理

響應(yīng)更快的 UI

事件驅(qū)動的 UI 工具箱(如 AWT 和 Swing)有一個事件線程,它處理 UI 事件,如擊鍵或鼠標(biāo)點擊。

AWT 和 Swing 程序把事件偵聽器與 UI 對象連接。當(dāng)特定事件(如單擊了某個按鈕)發(fā)生時,這些偵聽器會得到通知。事件偵聽器是在 AWT 事件線程中調(diào)用的。

如果事件偵聽器要執(zhí)行持續(xù)很久的任務(wù),如檢查一個大文檔中的拼寫,事件線程將忙于運行拼寫檢查器,所以在完成事件偵聽器之前,就不能處理額外的 UI 事件。這就會使程序看來似乎停滯了,讓用戶不知所措。

要避免使 UI 延遲響應(yīng),事件偵聽器應(yīng)該把較長的任務(wù)放到另一個線程中,這樣 AWT 線程在任務(wù)的執(zhí)行過程中就可以繼續(xù)處理 UI 事件(包括取消正在執(zhí)行的長時間運行任務(wù)的請求)。

利用多處理器系統(tǒng)

多處理器(MP)系統(tǒng)比過去更普及了。以前只能在大型數(shù)據(jù)中心和科學(xué)計算設(shè)施中才能找到它們?,F(xiàn)在許多低端服務(wù)器系統(tǒng) ― 甚至是一些臺式機系統(tǒng) ― 都有多個處理器。

現(xiàn)代操作系統(tǒng),包括 Linux、Solaris 和 Windows NT/2000,都可以利用多個處理器并調(diào)度線程在任何可用的處理器上執(zhí)行。

調(diào)度的基本單位通常是線程;如果某個程序只有一個活動的線程,它一次只能在一個處理器上運行。如果某個程序有多個活動線程,那么可以同時調(diào)度多個線程。在精心設(shè)計的程序中,使用多個線程可以提高程序吞吐量和性能。

簡化建模

在某些情況下,使用線程可以使程序編寫和維護起來更簡單。考慮一個仿真應(yīng)用程序,您要在其中模擬多個實體之間的交互作用。給每個實體一個自己的線程可以使許多仿真和對應(yīng)用程序的建模大大簡化。

另一個適合使用單獨線程來簡化程序的示例是在一個應(yīng)用程序有多個獨立的事件驅(qū)動的組件的時候。例如,一個應(yīng)用程序可能有這樣一個組件,該組件在某個事件之后用秒數(shù)倒計時,并更新屏幕顯示。與其讓一個主循環(huán)定期檢查時間并更新顯示,不如讓一個線程什么也不做,一直休眠,直到某一段時間后,更新屏幕上的計數(shù)器,這樣更簡單,而且不容易出錯。這樣,主線程就根本無需擔(dān)心計時器。

異步或后臺處理

服務(wù)器應(yīng)用程序從遠(yuǎn)程來源(如套接字)獲取輸入。當(dāng)讀取套接字時,如果當(dāng)前沒有可用數(shù)據(jù),那么對 SocketInputStream.read() 的調(diào)用將會阻塞,直到有可用數(shù)據(jù)為止。

如果單線程程序要讀取套接字,而套接字另一端的實體并未發(fā)送任何數(shù)據(jù),那么該程序只會永遠(yuǎn)等待,而不執(zhí)行其它處理。相反,程序可以輪詢套接字,查看是否有可用數(shù)據(jù),但通常不會使用這種做法,因為會影響性能。

但是,如果您創(chuàng)建了一個線程來讀取套接字,那么當(dāng)這個線程等待套接字中的輸入時,主線程就可以執(zhí)行其它任務(wù)。您甚至可以創(chuàng)建多個線程,這樣就可以同時讀取多個套接字。這樣,當(dāng)有可用數(shù)據(jù)時,您會迅速得到通知(因為正在等待的線程被喚醒),而不必經(jīng)常輪詢以檢查是否有可用數(shù)據(jù)。使用線程等待套接字的代碼也比輪詢更簡單、更不易出錯。

簡單,但有時有風(fēng)險

雖然 Java 線程工具非常易于使用,但當(dāng)您創(chuàng)建多線程程序時,應(yīng)該盡量避免一些風(fēng)險。

當(dāng)多個線程訪問同一數(shù)據(jù)項(如靜態(tài)字段、可全局訪問對象的實例字段或共享集合)時,需要確保它們協(xié)調(diào)了對數(shù)據(jù)的訪問,這樣它們都可以看到數(shù)據(jù)的一致視圖,而且相互不會干擾另一方的更改。為了實現(xiàn)這個目的,Java 語言提供了兩個關(guān)鍵字:synchronized 和 volatile。我們將稍后在本教程中研究這些關(guān)鍵字的用途和意義。

當(dāng)從多個線程中訪問變量時,必須確保對該訪問正確地進行了同步。對于簡單變量,將變量聲明成 volatile 也許就足夠了,但在大多數(shù)情況下,需要使用同步。

如果您將要使用同步來保護對共享變量的訪問,那么必須確保在程序中所有訪問該變量的地方都使用同步。

不要做過頭

雖然線程可以大大簡化許多類型的應(yīng)用程序,過度使用線程可能會危及程序的性能及其可維護性。線程消耗了資源。因此,在不降低性能的情況下,可以創(chuàng)建的線程的數(shù)量是有限制的。

尤其在單處理器系統(tǒng)中,使用多個線程不會使主要消耗 CPU 資源的程序運行得更快。

示例:使用一個線程用于計時,并使用另一個線程完成工作

以下示例使用兩個線程,一個用于計時,一個用于執(zhí)行實際工作。主線程使用非常簡單的算法計算素數(shù)。

在它啟動之前,它創(chuàng)建并啟動一個計時器線程,這個線程會休眠十秒鐘,然后設(shè)置一個主線程要檢查的標(biāo)志。十秒鐘之后,主線程將停止。請注意,共享標(biāo)志被聲明成 volatile。

/**
 * CalculatePrimes -- calculate as many primes as we can in ten seconds 
 */ 
 
public class CalculatePrimes extends Thread {
 
    public static final int MAX_PRIMES = 1000000;
    public static final int TEN_SECONDS = 10000;
 
    public volatile boolean finished = false;
 
    public void run() {
        int[] primes = new int[MAX_PRIMES];
        int count = 0;
 
        for (int i=2; count<MAX_PRIMES; i++) {
 
            // Check to see if the timer has expired
            if (finished) {
                break;
            }
 
            boolean prime = true;
            for (int j=0; j<count; j++) {
                if (i % primes[j] == 0) {
                    prime = false;
                    break;
                }
            }
 
            if (prime) {
                primes[count++] = i;
                System.out.println("Found prime: " + i);
            }
        }
    }
 
    public static void main(String[] args) {
        CalculatePrimes calculator = new CalculatePrimes();
        calculator.start();
        try {
            Thread.sleep(TEN_SECONDS);
        }
        catch (InterruptedException e) {
            // fall through
        }
 
        calculator.finished = true;
    }
}

Java 語言包含了內(nèi)置在語言中的功能強大的線程工具。您可以將線程工具用于:

增加 GUI 應(yīng)用程序的響應(yīng)速度

利用多處理器系統(tǒng)

當(dāng)程序有多個獨立實體時,簡化程序邏輯

在不阻塞整個程序的情況下,執(zhí)行阻塞 I/O

當(dāng)使用多個線程時,必須謹(jǐn)慎,遵循在線程之間共享數(shù)據(jù)的規(guī)則,我們將在共享對數(shù)據(jù)的訪問 中討論這些規(guī)則。所有這些規(guī)則歸結(jié)為一條基本原則:不要忘了同步。

感謝各位的閱讀!看完上述內(nèi)容,你們對java線程的作用是什么大概了解了嗎?希望文章內(nèi)容對大家有所幫助。如果想了解更多相關(guān)文章內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI