您好,登錄后才能下訂單哦!
小編給大家分享一下Java線程有什么用,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
一、為什么要研究和使用線程
一般來說,計算機正在執行的程序稱作進程(process),進程有不同的地址空間并且是在同一系統上運行的不同程序,如WORD和Excel,進程間的通訊是很費時而且有限的。上下文切換、改變運行的進程也是非常復雜的。進程間通訊復雜,可能需要管道、消息隊列、共享內存 (sharedmemory)或信號處理來保證進程間的通訊。盡管許多程序都在運行,但一次只能與一個程序打交道。
線程(thread)是指進程中單一順序的控制流。又稱為輕量級進程。線程則共享相同的地址空間并共同構成一個大的進程。線程間的通訊是非常簡單而有效的,上下文切換非常快并且是整個大程序的一部分切換。線程僅是過程調用,它們彼此獨立執行,線程使得在一個應用程序中,程序的編寫更加自由和豐富。線程的興趣在于,一個程序中同時使用多個線程來完成不同的任務。因此如果很好地利用線程,可以大大簡化應用程序設計。多線程可以增進程序的交互性,提供更好的能力和功能、更好的GUI和更好的服務器功能。給二個例子說明如下:
例一:利用多線程并行機制可以很好地解決交互式網絡程序中的許多問題,如:大量的網絡文件資源的讀寫、用戶輸入響應、動畫顯示等問題不需要CPU的多少時間;而耗時的復雜計算通常并不需要立即響應,所以無需將CPU全給它。例如,從一個慢速的網絡上讀取一數據流也許要1分鐘時間,但需要CPU參與傳輸數據的時間則非常短;響應用戶的輸入如擊鍵,就算最快的輸入員,1秒鐘擊鍵10次,也不需要CPU的多少時間。動畫程序比較耗時,一幅畫在1秒內要重繪5-10次,但CPU在大部分時間仍處于空閑狀態。在傳統的單線程環境下的問題是用戶必須等待每個任務完成后才能進行下一個任務。即使CPU大部分時間空閑,也只能按步就班地工作。多線程可以很好地解決這些問題避免引起用戶的等待。如:耗時的復雜計算應用就可劃分成兩個控制線程:一個處理GUI的用戶事件,另一個進行后臺計算。
例二:如并發服務器,它面向不定長時間內處理完的請求,對每個請求由服務器的線程處理。傳統的并發服務器往往是基于多進程機制的,每個客戶一個進程,需要操作系統的干預,進程的數目受操作系統的限制。本文利用Java的線程機制建立了基于多線程的并發服務器。生成和管理他們是相當簡單的操作。線程被用來建立請求驅動的服務程序,每個客戶一個線程,多個線程可以并發執行。特別地線程具有如下特性(1)線程共享父進程的所有程序和數據(2)有自身的運行單元(3)有它自己的私有存儲和執行環境(尤其是處理器寄存器),使得服務器進程不隨客戶數的增加而線性增加。可減少服務器進程的壓力,降低開銷,充分利用CPU的資源。以上并發服務器在某一瞬間由同一服務器進程所產生的多個并發線程對多個客戶的并發請求采取分而治之的措施,從而解決了并發請求的問題。各線程即可以獨立操作,又可以協同作業。降低了服務器的復雜度。
Java是基于操作系統級的多線程環境之上設計的,Java的運行器依靠多線程來執行任務,并且所有類庫在設計時都考慮到多線程機制。
二、Java線程的結構
Java支持一種“搶占式”(preemptive)調度方式。
線程從產生到消失,可分5個狀態:
Newborn
線程在己被創建但未執行這段時間內,處于一個特殊的"Newborn"狀態,這時,線程對象己被分配內存空間,其私有數據己被初始化,但該線程還未被調度。此時線程對象可通過start()方法調度,或者利用stop()方法殺死.新創建的線程一旦被調度,就將切換到"Runnable"狀態。
Runnable
Runnable意即線程的就緒狀態,表示線程正等待處理器資源,隨時可被調用執行。處于就緒狀態的線程事實上己被調度,也就是說,它們己經被放到某一隊列等待執行。處于就緒狀態的線程何時可真正執行,取決于線程優先級以及隊列的當前狀況。線程的優先級如果相同,將遵循"先來先服務"的調度原則。
線程依據自身優先級進入等待隊列的相應位置。某些系統線程具有最高優先級,這些最高優先級線程一旦進入就緒狀態,將搶占當前正在執行的線程的處理器資源,當前線程只能重新在等待隊列尋找自己的位置.這些具有最高優先級的線程執行完自己的任務之后,將睡眠一段時間,等待被某一事件喚醒.一旦被喚,這些線程就又開始搶占處理器資源。這些最高優先級線程通常用來執行一些關鍵性任務,如屏幕顯示。
低優先級線程需等待更長的時間才能有機會運行。由于系統本身無法中止高優先級線程的執行,因此,如果你的程序中用到了優先級較高的線程對象,那么最好不時讓這些線程放棄對處理器資源的控制權,以使其他線程能夠有機運行。
Running
"Running"(運行)狀態表明線程正在運行,該線己經擁有了對處理器的控制權,其代碼目前正在運行。這個線程將一直運行直到運行完畢,除非運行過程的控制權被一優先級更高的線程強占。
綜合起來,線程在如下3種情形之下將釋放對處理器的控制權:
1.主動或被動地釋放對處理器資源的控制權。這時,該線程必須再次進入等待隊列,等待其他優先級高或相等線程執行完畢。
2.睡眠一段確定的時間,不進入等待隊列。這段確定的時間段到期之后,重新開始運行。
3.等待某一事件喚醒自己。
Blocked
一個線程如果處于"Blocked"(堵塞)狀態,那么暫時這個線程將無法進入就緒隊列。處于堵塞狀態的線程通常必須由某些事件才能喚醒。至于是何種事件,則取決于堵塞發生的原因:處于睡眠中的線程必須被堵塞一段固定的時間;被掛起、或處于消息等待狀態的線程則必須由一外來事件喚醒。
Dead
Dead表示線程巳退出運行狀態,并且不再進入就緒隊列.其中原因可能是線程巳執行完畢(正常結束),也可能是該線程被另一線程所強行中斷(kill)。
三、創建和使用線程的基本方法
1.線程的產生
在Java語言中,可采用兩種方式產生線程:一是實現一個Runnable界面,二是擴充一個Thread類.java.lang中定義了一個直接從根類Object中派生的Thread類.所有以這個類派生的子類或間接子類,均為線程。在這種方式中,需要作為一個線程執行的類只能繼承、擴充單一的父類。下面的例子通過擴充Thread類,用該線程自己的實現來覆蓋Thread.run(),產生一個新類Counter。run()方法是 Counter類線程所作的全部操作.
import java.lang.*; public class Counter extends Thread { public void run () {....} }
實現Runnable界面是最常用的產生線程的方法,它打破了擴充Thread類方式的限制。
Java語言源碼中,Runnable界面只包含了一個抽象方法,其定義如下:
package java.lang.*; public interface Runnable { public abstract void run (); }
所有實現了Runnable界面的類的對象都可以以線程方式執行.下面的例子產生與上面例子相同的類.可以看到counter類中使用了一個Thread類的變量.
import java.lang.*;
public class counter implements Runnable { Thread T; public void run () {...} }
2、基本方法
.public synchronized void start()
啟動線程對象,調用其run()方法,隨即返回。
.pubilc final void stop()
停止線程的執行。
.public final void resume()
喚醒被掛起的線程。只在調用suspend()之后有效。
.public final void suspend()
掛起線程的執行。
.public static void yield()
暫時中止當前正在執行的線程對象的運行。若存在其他線程,則隨后調用下一個線程。
.public static void sleep(longmills)throws Inter rupted Exception
使當前正處運行狀態的線程睡眠mills毫秒。
.public final void wait()throws Interrupted Exception
使線程進入等待狀態,直到被另一線程喚醒
.public final void motify()
把線程狀態的變化通知給另一等待線程。
四、線程的同步
線程的使用,主要在于一個進程中多個線程的協同工作,所以線程的同步就很重要。線程的同步用于線程共享數據,轉換和控制線程的執行,保證內存的一致性。
在Java中,運行環境使用程序(Monitor)來解決線程同步的問題。管程是一種并發同步機制,它包括用于分配一個特定的共享資源或一組共享資源的數據和方法.
Java為每一個擁有synchronized方法的對象實例提供了一個唯一的管程。為了完成分配資源的功能,線程必須調用管程入口。管程入口就是synchronized方法入口。當調用同步(synchronized)方法時,該線程就獲得了該管程。
管程邊界上實行嚴格的互斥,在同一時刻,只允許一個線程進入管程;當管程中已有了一個線程時,其它希望進入管程的線程必須等待,這種等待是由管程自動管理的。
如果調用管程入口的線程發現資源已被分配,管程中的這個線程將調用等待操作wait()。進入wait()后,該線程放棄占用管程,在管程外面等待,以便其它線程進入管程。
最終,占用資源的線程將調用一個管程的入口把資源歸還給系統,此時,該線程需調用一個通知操作notify(),通知系統允許其中一個等待的線程獲得管程并得到資源。被通知的線程是排隊的,從而避免無限拖延。
在Java.lang中提供了用來編寫管程的兩個方法:notify()和wait()。此外還有notifyAll(),它通知所有等待的線程,使它們競爭管程,結果是其中一個獲得管程,其佘返回等待狀態。
五、線程的控制
線程的控制分為停止線程和啟動線程。
.publicfinalvoidsuspend()
掛起線程的執行。
.publicfinalvoidresume()
喚醒被掛起的線程。使一個暫停的線程可用于調度。
因為線程的調度為搶占式機制,也可使用線程的優先級來對線程進行控制。
.publicfinalvoidsetPriority(intnewPriority)
設置線程優先級。
.publicfinalintgetPriority()
獲取并返回線程的優先級。
線程的優先級用于在運行隊列中給線程排序,Java提供的搶占式調度,使得高級別的線程先運行。
六、線程的應用
在實際應用中,線程使用的范圍很廣,可用于控制實時數據處理、快速的網絡服務,還有更快的圖象繪制和打印,以及數據庫中的數據的取回和處理等等。在Java中一個在不停運行的提供一些基本服務的例子是垃圾收集線程,垃圾收集線程,。該線程由Java虛擬機提供。它掃描程序中不再被訪問的變量,將其所占的系統資源釋放給系統。
以上是“Java線程有什么用”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。