亚欧洲精品在线观看,窝窝影院午夜看片,久久国产成人午夜av影院宅,午夜91,免费国产人成网站,ts在线视频,欧美激情在线一区

java語言

java的多線程

時間:2025-04-09 02:19:12 java語言 我要投稿

java的多線程

  認識多任務、多進程、單線程、多線程

  要認識多線程就要從操作系統(tǒng)的原理說起。

  以前古老的DOS操作系統(tǒng)(V 6.22)是單任務的,還沒有線程的概念,系統(tǒng)在每次只能做一件事情。比如你在copy東西的時候不能rename文件名。為了提高系統(tǒng)的利用效率,采用批處理來批量執(zhí)行任務。

  現(xiàn)在的操作系統(tǒng)都是多任務操作系統(tǒng),每個運行的任務就是操作系統(tǒng)所做的一件事情,比如你在聽歌的同時還在用MSN和好友聊天。聽歌和聊天就是兩個任務,這個兩個任務是“同時”進行的。一個任務一般對應一個進程,也可能包含好幾個進程。比如運行的MSN就對應一個MSN的進程,如果你用的是windows系統(tǒng),你就可以在任務管理器中看到操作系統(tǒng)正在運行的進程信息。

  一般來說,當運行一個應用程序的時候,就啟動了一個進程,當然有些會啟動多個進程。啟動進程的時候,操作系統(tǒng)會為進程分配資源,其中最主要的資源是內(nèi)存空間,因為程序是在內(nèi)存中運行的。在進程中,有些程序流程塊是可以亂序執(zhí)行的,并且這個代碼塊可以同時被多次執(zhí)行。實際上,這樣的代碼塊就是線程體。線程是進程中亂序執(zhí)行的代碼流程。當多個線程同時運行的時候,這樣的執(zhí)行模式成為并發(fā)執(zhí)行。

  多線程的目的是為了最大限度的利用CPU資源。

  Java編寫程序都運行在在Java虛擬機(JVM)中,在JVM的內(nèi)部,程序的多任務是通過線程來實現(xiàn)的。每用java命令啟動一個java應用程序,就會啟動一個JVM進程。在同一個JVM進程中,有且只有一個進程,就是它自己。在這個JVM環(huán)境中,所有程序代碼的運行都是以線程來運行。

  一般常見的Java應用程序都是單線程的。比如,用java命令運行一個最簡單的HelloWorld的Java應用程序時,就啟動了一個JVM進程,JVM找到程序程序的入口點main(),然后運行main()方法,這樣就產(chǎn)生了一個線程,這個線程稱之為主線程。當main方法結束后,主線程運行完成。JVM進程也隨即退出 。

  對于一個進程中的多個線程來說,多個線程共享進程的內(nèi)存塊,當有新的線程產(chǎn)生的時候,操作系統(tǒng)不分配新的內(nèi)存,而是讓新線程共享原有的進程塊的內(nèi)存。因此,線程間的通信很容易,速度也很快。不同的進程因為處于不同的內(nèi)存塊,因此進程之間的通信相對困難。

  實際上,操作的系統(tǒng)的多進程實現(xiàn)了多任務并發(fā)執(zhí)行,程序的多線程實現(xiàn)了進程的并發(fā)執(zhí)行。多任務、多進程、多線程的前提都是要求操作系統(tǒng)提供多任務、多進程、多線程的支持。

  在Java程序中,JVM負責線程的調(diào)度。線程調(diào)度是值按照特定的機制為多個線程分配CPU的使用權。

  調(diào)度的模式有兩種:分時調(diào)度和搶占式調(diào)度。分時調(diào)度是所有線程輪流獲得CPU使用權,并平均分配每個線程占用CPU的時間;搶占式調(diào)度是根據(jù)線程的優(yōu)先級別來獲取CPU的使用權。JVM的線程調(diào)度模式采用了搶占式模式。

  所謂的“并發(fā)執(zhí)行”、“同時”其實都不是真正意義上的“同時”。眾所周知,CPU都有個時鐘頻率,表示每秒中能執(zhí)行cpu指令的次數(shù)。在每個時鐘周期內(nèi),CPU實際上只能去執(zhí)行一條(也有可能多條)指令。操作系統(tǒng)將進程線程進行管理,輪流(沒有固定的順序)分配每個進程很短的一段是時間(不一定是均分),然后在每個線程內(nèi)部,程序代碼自己處理該進程內(nèi)部線程的時間分配,多個線程之間相互的切換去執(zhí)行,這個切換時間也是非常短的。因此多任務、多進程、多線程都是操作系統(tǒng)給人的一種宏觀感受,從微觀角度看,程序的運行是異步執(zhí)行的。

  Java語言的多線程需要操作系統(tǒng)的支持。

  Java 虛擬機允許應用程序并發(fā)地運行多個執(zhí)行線程。Java語言提供了多線程編程的擴展點,并給出了功能強大的線程控制API。

  在Java中,多線程的實現(xiàn)有兩種方式:

  擴展java.lang.Thread類

  實現(xiàn)java.lang.Runnable接口

  每個線程都有一個優(yōu)先級,高優(yōu)先級線程的執(zhí)行優(yōu)先于低優(yōu)先級線程。每個線程都可以或不可以標記為一個守護程序。當某個線程中運行的代碼創(chuàng)建一個新 Thread 對象時,該新線程的初始優(yōu)先級被設定為創(chuàng)建線程的優(yōu)先級,并且當且僅當創(chuàng)建線程是守護線程時,新線程才是守護程序。

  當 Java 虛擬機啟動時,通常都會有單個非守護線程(它通常會調(diào)用某個指定類的 main 方法)。Java 虛擬機會繼續(xù)執(zhí)行線程,直到下列任一情況出現(xiàn)時為止:

  調(diào)用了 Runtime 類的 exit 方法,并且安全管理器允許退出操作發(fā)生。

  非守護線程的所有線程都已停止運行,無論是通過從對 run 方法的調(diào)用中返回,還是通過拋出一個傳播到 run 方法之外的異常。

  線程的生命周期:

  新建狀態(tài):用new語句創(chuàng)建的線程對象處于新建狀態(tài),此時它和其它的java對象一樣,僅僅在堆中被分配了內(nèi)存

  就緒狀態(tài):當一個線程創(chuàng)建了以后,其他的線程調(diào)用了它的start()方法,該線程就進入了就緒狀態(tài)。處于這個狀態(tài)的線程位于可運行池中,等待獲得CPU的使用權

  運行狀態(tài):處于這個狀態(tài)的線程占用CPU,執(zhí)行程序的代碼

  阻塞狀態(tài):當線程處于阻塞狀態(tài)時,java虛擬機不會給線程分配CPU,直到線程重新進入就緒狀態(tài),它才有機會轉到運行狀態(tài)。

  阻塞狀態(tài)分為三種情況:

  1、 位于對象等待池中的阻塞狀態(tài):當線程運行時,如果執(zhí)行了某個對象的wait()方法,java虛擬機就回把線程放到這個對象的等待池中

  2、 位于對象鎖中的阻塞狀態(tài),當線程處于運行狀態(tài)時,試圖獲得某個對象的同步鎖時,如果該對象的同步鎖已經(jīng)被其他的線程占用,JVM就會把這個線程放到這個對象的瑣池中。

  3、 其它的阻塞狀態(tài):當前線程執(zhí)行了sleep()方法,或者調(diào)用了其它線程的join()方法,或者發(fā)出了I/O請求時,就會進入這個狀態(tài)中。

  一、創(chuàng)建并運行線程

  當調(diào)用start方法后,線程開始執(zhí)行run方法中的代碼。線程進入運行狀態(tài)。可以通過Thread類的isAlive方法來判斷線程是否處于運行狀態(tài)。當線程處于運行狀態(tài)時,isAlive返回true,當isAlive返回false時,可能線程處于等待狀態(tài),也可能處于停止狀態(tài)。

  二、掛起和喚醒線程

  一但線程開始執(zhí)行run方法,就會一直到這個run方法執(zhí)行完成這個線程才退出。但在線程執(zhí)行的過程中,可以通過兩個方法使線程暫時停止執(zhí)行。這兩個方法是suspend和sleep。在使用suspend掛起線程后,可以通過resume方法喚醒線程。而使用sleep使線程休眠后,只能在設定的時間后使線程處于就緒狀態(tài)(在線程休眠結束后,線程不一定會馬上執(zhí)行,只是進入了就緒狀態(tài),等待著系統(tǒng)進行調(diào)度)。

  雖然suspend和resume可以很方便地使線程掛起和喚醒,但由于使用這兩個方法可能會造成一些不可預料的事情發(fā)生,因此,這兩個方法被標識為deprecated(抗議)標記,這表明在以后的jdk版本中這兩個方法可能被刪除,所以盡量不要使用這兩個方法來操作線程。下面的代碼演示了sleep、suspend和resume三個方法的使用。

  三、終止線程的三種方法

  有三種方法可以使終止線程。

  1. 使用退出標志,使線程正常退出,也就是當run方法完成后線程終止。

  2. 使用stop方法強行終止線程(這個方法不推薦使用,因為stop和suspend、resume一樣,也可能發(fā)生不可預料的結果)。

  3. 使用interrupt方法中斷線程。

  數(shù)據(jù)同步:

  線程同步的特征:

  1、 如果一個同步代碼塊和非同步代碼塊同時操作共享資源,仍然會造成對共享資源的競爭。因為當一個線程執(zhí)行一個對象的同步代碼塊時,其他的線程仍然可以執(zhí)行對象的非同步代碼塊。(所謂的線程之間保持同步,是指不同的線程在執(zhí)行同一個對象的同步代碼塊時,因為要獲得對象的同步鎖而互相牽制)

  2、 每個對象都有唯一的同步鎖

  3、 在靜態(tài)方法前面可以使用synchronized修飾符。

  4、 當一個線程開始執(zhí)行同步代碼塊時,并不意味著必須以不間斷的方式運行,進入同步代碼塊的線程可以執(zhí)行Thread.sleep()或者執(zhí)行Thread.yield()方法,此時它并不釋放對象鎖,只是把運行的機會讓給其他的線程。

  5、 Synchronized聲明不會被繼承,如果一個用synchronized修飾的方法被子類覆蓋,那么子類中這個方法不在保持同步,除非用synchronized修飾。

【java的多線程】相關文章:

java多線程08-31

java語言的多線程08-29

java多線程介紹08-23

java多線程教程11-03

如何使用java多線程08-23

Java多線程問題總結10-24

Java使用多線程的優(yōu)勢07-10

Java多線程基本使用11-08

Java多線程的用法介紹09-15