溫馨提示×

溫馨提示×

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

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

Java線程有什么用

發(fā)布時間:2022-01-06 09:17:27 來源:億速云 閱讀:488 作者:小新 欄目:編程語言

小編給大家分享一下Java線程有什么用,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

一、為什么要研究和使用線程
一般來說,計算機正在執(zhí)行的程序稱作進程(process),進程有不同的地址空間并且是在同一系統(tǒng)上運行的不同程序,如WORD和Excel,進程間的通訊是很費時而且有限的。上下文切換、改變運行的進程也是非常復雜的。進程間通訊復雜,可能需要管道、消息隊列、共享內(nèi)存 (sharedmemory)或信號處理來保證進程間的通訊。盡管許多程序都在運行,但一次只能與一個程序打交道。
線程(thread)是指進程中單一順序的控制流。又稱為輕量級進程。線程則共享相同的地址空間并共同構(gòu)成一個大的進程。線程間的通訊是非常簡單而有效的,上下文切換非常快并且是整個大程序的一部分切換。線程僅是過程調(diào)用,它們彼此獨立執(zhí)行,線程使得在一個應用程序中,程序的編寫更加自由和豐富。線程的興趣在于,一個程序中同時使用多個線程來完成不同的任務。因此如果很好地利用線程,可以大大簡化應用程序設計。多線程可以增進程序的交互性,提供更好的能力和功能、更好的GUI和更好的服務器功能。給二個例子說明如下:

例一:利用多線程并行機制可以很好地解決交互式網(wǎng)絡程序中的許多問題,如:大量的網(wǎng)絡文件資源的讀寫、用戶輸入響應、動畫顯示等問題不需要CPU的多少時間;而耗時的復雜計算通常并不需要立即響應,所以無需將CPU全給它。例如,從一個慢速的網(wǎng)絡上讀取一數(shù)據(jù)流也許要1分鐘時間,但需要CPU參與傳輸數(shù)據(jù)的時間則非常短;響應用戶的輸入如擊鍵,就算最快的輸入員,1秒鐘擊鍵10次,也不需要CPU的多少時間。動畫程序比較耗時,一幅畫在1秒內(nèi)要重繪5-10次,但CPU在大部分時間仍處于空閑狀態(tài)。在傳統(tǒng)的單線程環(huán)境下的問題是用戶必須等待每個任務完成后才能進行下一個任務。即使CPU大部分時間空閑,也只能按步就班地工作。多線程可以很好地解決這些問題避免引起用戶的等待。如:耗時的復雜計算應用就可劃分成兩個控制線程:一個處理GUI的用戶事件,另一個進行后臺計算。

例二:如并發(fā)服務器,它面向不定長時間內(nèi)處理完的請求,對每個請求由服務器的線程處理。傳統(tǒng)的并發(fā)服務器往往是基于多進程機制的,每個客戶一個進程,需要操作系統(tǒng)的干預,進程的數(shù)目受操作系統(tǒng)的限制。本文利用Java的線程機制建立了基于多線程的并發(fā)服務器。生成和管理他們是相當簡單的操作。線程被用來建立請求驅(qū)動的服務程序,每個客戶一個線程,多個線程可以并發(fā)執(zhí)行。特別地線程具有如下特性(1)線程共享父進程的所有程序和數(shù)據(jù)(2)有自身的運行單元(3)有它自己的私有存儲和執(zhí)行環(huán)境(尤其是處理器寄存器),使得服務器進程不隨客戶數(shù)的增加而線性增加??蓽p少服務器進程的壓力,降低開銷,充分利用CPU的資源。以上并發(fā)服務器在某一瞬間由同一服務器進程所產(chǎn)生的多個并發(fā)線程對多個客戶的并發(fā)請求采取分而治之的措施,從而解決了并發(fā)請求的問題。各線程即可以獨立操作,又可以協(xié)同作業(yè)。降低了服務器的復雜度。

Java是基于操作系統(tǒng)級的多線程環(huán)境之上設計的,Java的運行器依靠多線程來執(zhí)行任務,并且所有類庫在設計時都考慮到多線程機制。

二、Java線程的結(jié)構(gòu)
Java支持一種“搶占式”(preemptive)調(diào)度方式。
線程從產(chǎn)生到消失,可分5個狀態(tài):
Newborn
線程在己被創(chuàng)建但未執(zhí)行這段時間內(nèi),處于一個特殊的"Newborn"狀態(tài),這時,線程對象己被分配內(nèi)存空間,其私有數(shù)據(jù)己被初始化,但該線程還未被調(diào)度。此時線程對象可通過start()方法調(diào)度,或者利用stop()方法殺死.新創(chuàng)建的線程一旦被調(diào)度,就將切換到"Runnable"狀態(tài)。

Runnable
Runnable意即線程的就緒狀態(tài),表示線程正等待處理器資源,隨時可被調(diào)用執(zhí)行。處于就緒狀態(tài)的線程事實上己被調(diào)度,也就是說,它們己經(jīng)被放到某一隊列等待執(zhí)行。處于就緒狀態(tài)的線程何時可真正執(zhí)行,取決于線程優(yōu)先級以及隊列的當前狀況。線程的優(yōu)先級如果相同,將遵循"先來先服務"的調(diào)度原則。

線程依據(jù)自身優(yōu)先級進入等待隊列的相應位置。某些系統(tǒng)線程具有最高優(yōu)先級,這些最高優(yōu)先級線程一旦進入就緒狀態(tài),將搶占當前正在執(zhí)行的線程的處理器資源,當前線程只能重新在等待隊列尋找自己的位置.這些具有最高優(yōu)先級的線程執(zhí)行完自己的任務之后,將睡眠一段時間,等待被某一事件喚醒.一旦被喚,這些線程就又開始搶占處理器資源。這些最高優(yōu)先級線程通常用來執(zhí)行一些關(guān)鍵性任務,如屏幕顯示。

低優(yōu)先級線程需等待更長的時間才能有機會運行。由于系統(tǒng)本身無法中止高優(yōu)先級線程的執(zhí)行,因此,如果你的程序中用到了優(yōu)先級較高的線程對象,那么最好不時讓這些線程放棄對處理器資源的控制權(quán),以使其他線程能夠有機運行。

Running
"Running"(運行)狀態(tài)表明線程正在運行,該線己經(jīng)擁有了對處理器的控制權(quán),其代碼目前正在運行。這個線程將一直運行直到運行完畢,除非運行過程的控制權(quán)被一優(yōu)先級更高的線程強占。

綜合起來,線程在如下3種情形之下將釋放對處理器的控制權(quán):

1.主動或被動地釋放對處理器資源的控制權(quán)。這時,該線程必須再次進入等待隊列,等待其他優(yōu)先級高或相等線程執(zhí)行完畢。

2.睡眠一段確定的時間,不進入等待隊列。這段確定的時間段到期之后,重新開始運行。

3.等待某一事件喚醒自己。

Blocked
一個線程如果處于"Blocked"(堵塞)狀態(tài),那么暫時這個線程將無法進入就緒隊列。處于堵塞狀態(tài)的線程通常必須由某些事件才能喚醒。至于是何種事件,則取決于堵塞發(fā)生的原因:處于睡眠中的線程必須被堵塞一段固定的時間;被掛起、或處于消息等待狀態(tài)的線程則必須由一外來事件喚醒。

Dead
Dead表示線程巳退出運行狀態(tài),并且不再進入就緒隊列.其中原因可能是線程巳執(zhí)行完畢(正常結(jié)束),也可能是該線程被另一線程所強行中斷(kill)。

三、創(chuàng)建和使用線程的基本方法
1.線程的產(chǎn)生
在Java語言中,可采用兩種方式產(chǎn)生線程:一是實現(xiàn)一個Runnable界面,二是擴充一個Thread類.java.lang中定義了一個直接從根類Object中派生的Thread類.所有以這個類派生的子類或間接子類,均為線程。在這種方式中,需要作為一個線程執(zhí)行的類只能繼承、擴充單一的父類。下面的例子通過擴充Thread類,用該線程自己的實現(xiàn)來覆蓋Thread.run(),產(chǎn)生一個新類Counter。run()方法是 Counter類線程所作的全部操作.
import java.lang.*; public class Counter extends Thread { public void run () {....} }

實現(xiàn)Runnable界面是最常用的產(chǎn)生線程的方法,它打破了擴充Thread類方式的限制。
Java語言源碼中,Runnable界面只包含了一個抽象方法,其定義如下:
package java.lang.*; public interface Runnable { public abstract void run (); }

所有實現(xiàn)了Runnable界面的類的對象都可以以線程方式執(zhí)行.下面的例子產(chǎn)生與上面例子相同的類.可以看到counter類中使用了一個Thread類的變量.
import java.lang.*;
public class counter implements Runnable { Thread T; public void run () {...} }
2、基本方法
.public synchronized void start()

啟動線程對象,調(diào)用其run()方法,隨即返回。

.pubilc final void stop()

停止線程的執(zhí)行。

.public final void resume()

喚醒被掛起的線程。只在調(diào)用suspend()之后有效。

.public final void suspend()

掛起線程的執(zhí)行。

.public static void yield()

暫時中止當前正在執(zhí)行的線程對象的運行。若存在其他線程,則隨后調(diào)用下一個線程。

.public static void sleep(longmills)throws Inter rupted Exception

使當前正處運行狀態(tài)的線程睡眠mills毫秒。

.public final void wait()throws Interrupted Exception

使線程進入等待狀態(tài),直到被另一線程喚醒

.public final void motify()

把線程狀態(tài)的變化通知給另一等待線程。

四、線程的同步
線程的使用,主要在于一個進程中多個線程的協(xié)同工作,所以線程的同步就很重要。線程的同步用于線程共享數(shù)據(jù),轉(zhuǎn)換和控制線程的執(zhí)行,保證內(nèi)存的一致性。
在Java中,運行環(huán)境使用程序(Monitor)來解決線程同步的問題。管程是一種并發(fā)同步機制,它包括用于分配一個特定的共享資源或一組共享資源的數(shù)據(jù)和方法.

Java為每一個擁有synchronized方法的對象實例提供了一個唯一的管程。為了完成分配資源的功能,線程必須調(diào)用管程入口。管程入口就是synchronized方法入口。當調(diào)用同步(synchronized)方法時,該線程就獲得了該管程。

管程邊界上實行嚴格的互斥,在同一時刻,只允許一個線程進入管程;當管程中已有了一個線程時,其它希望進入管程的線程必須等待,這種等待是由管程自動管理的。

如果調(diào)用管程入口的線程發(fā)現(xiàn)資源已被分配,管程中的這個線程將調(diào)用等待操作wait()。進入wait()后,該線程放棄占用管程,在管程外面等待,以便其它線程進入管程。

最終,占用資源的線程將調(diào)用一個管程的入口把資源歸還給系統(tǒng),此時,該線程需調(diào)用一個通知操作notify(),通知系統(tǒng)允許其中一個等待的線程獲得管程并得到資源。被通知的線程是排隊的,從而避免無限拖延。

在Java.lang中提供了用來編寫管程的兩個方法:notify()和wait()。此外還有notifyAll(),它通知所有等待的線程,使它們競爭管程,結(jié)果是其中一個獲得管程,其佘返回等待狀態(tài)。

五、線程的控制
線程的控制分為停止線程和啟動線程。
.publicfinalvoidsuspend()

掛起線程的執(zhí)行。

.publicfinalvoidresume()

喚醒被掛起的線程。使一個暫停的線程可用于調(diào)度。

因為線程的調(diào)度為搶占式機制,也可使用線程的優(yōu)先級來對線程進行控制。

.publicfinalvoidsetPriority(intnewPriority)

設置線程優(yōu)先級。

.publicfinalintgetPriority()

獲取并返回線程的優(yōu)先級。

線程的優(yōu)先級用于在運行隊列中給線程排序,Java提供的搶占式調(diào)度,使得高級別的線程先運行。

六、線程的應用
在實際應用中,線程使用的范圍很廣,可用于控制實時數(shù)據(jù)處理、快速的網(wǎng)絡服務,還有更快的圖象繪制和打印,以及數(shù)據(jù)庫中的數(shù)據(jù)的取回和處理等等。在Java中一個在不停運行的提供一些基本服務的例子是垃圾收集線程,垃圾收集線程,。該線程由Java虛擬機提供。它掃描程序中不再被訪問的變量,將其所占的系統(tǒng)資源釋放給系統(tǒng)。

以上是“Java線程有什么用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學習更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責聲明:本站發(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