国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

Java基礎之多線程簡述

2019-11-14 22:17:20
字體:
來源:轉載
供稿:網友
java基礎之多線程簡述

  首先,要辨析進程與線程的概念:

  進程是程序執(zhí)行的過程,它持有資源和線程,相對于程序本身而言具有動態(tài)性。

  線程是系統(tǒng)中最小的執(zhí)行單元,同一個進程中可能有多個線程,它們共享該進程持有的資源。線程的通信也稱為線程的交互,方式主要有互斥和同步。同步是指線程之間通過共同協(xié)作完成某項工作,線程間具有次序性;互斥是指線程間對某一資源的競爭,一次只能有一個線程訪問該資源。

  介紹完了這些基本概念,下面簡單介紹一下Java對多線程的支持.

  java中通過類Thread和接口Runnable來實現(xiàn)多線程的操作。它們都有一個run方法來指定線程工作時執(zhí)行的代碼。

Thread類的常用方法

類別

名稱

簡介

線程的創(chuàng)建

Thread()

Thread(String name)

Thread(Runnable target)

Thread(Runnable target, String name)

線程的方法

void start()

啟動線程

static void sleep(long millis)

線程休眠

static void sleep(long millis, int nanos)

void join()

某線程調用join方法后,使其他線程等待該線程終止

void join(long millis)

void join(long millis, int nanos)

static void yield()

當前正在運行的線程立刻釋放處理器,重新加入競爭處理器的隊列

獲取線程引用

static Thread currentThread()

返回當前正在運行的線程的引用

  使用多線程有兩種方式,一種是直接繼承Thread類,一種是實現(xiàn)Runnable接口

  • 繼承Thread類,在run方法中指定需要線程執(zhí)行的代碼,通過getName()和setName()方法去訪問線程名稱。通過該類對象的start方法來開啟線程。
  • 實現(xiàn)Runnable接口,重寫run方法來指定需要線程執(zhí)行的代碼,然后把該類的對象作為參數傳遞給Thread對象來執(zhí)行。

  另外,通過volatile關鍵字聲明的成員變量可以保證當其他線程修改該成員變量后,本線程可以正確讀取到此成員變量的值。

線程的狀態(tài)

  請結合OS中進程的5態(tài)來思考。以下線程狀態(tài)和方法的介紹來自DreamSea(張小哲)

  • 新生狀態(tài)(New):當一個線程的實例被創(chuàng)建即使用new關鍵字和Thread類或其子類創(chuàng)建一個線程對象后,此時該線程處于新生(new)狀態(tài),處于新生狀態(tài)的線程有自己的內存空間,但該線程并沒有運行,此時線程還不是活著的(not alive);
  • 就緒狀態(tài)(Runnable):通過調用線程實例的start()方法來啟動線程使線程進入就緒狀態(tài)(runnable);處于就緒狀態(tài)的線程已經具備了運行條件,但還沒有被分配到CPU即不一定會被立即執(zhí)行,此時處于線程就緒隊列,等待系統(tǒng)為其分配CPCU,等待狀態(tài)并不是執(zhí)行狀態(tài); 此時線程是活著的(alive);
  • 運行狀態(tài)(Running):一旦獲取CPU(被JVM選中),線程就進入運行(running)狀態(tài),線程的run()方法才開始被執(zhí)行;在運行狀態(tài)的線程執(zhí)行自己的run()方法中的操作,直到調用其他的方法而終止、或者等待某種資源而阻塞、或者完成任務而死亡;如果在給定的時間片內沒有執(zhí)行結束,就會被系統(tǒng)給換下來回到線程的等待狀態(tài);此時線程是活著的(alive);
  • 阻塞狀態(tài)(Blocked):通過調用join()、sleep()、wait()或者資源被暫用使線程處于阻塞(blocked)狀態(tài);處于Blocking狀態(tài)的線程仍然是活著的(alive)
  • 死亡狀態(tài)(Dead):當一個線程的run()方法運行完畢或被中斷或被異常退出,該線程到達死亡(dead)狀態(tài)。此時可能仍然存在一個該Thread的實例對象,當該Thread已經不可能在被作為一個可被獨立執(zhí)行的線程對待了,線程的獨立的call stack已經被dissolved。一旦某一線程進入Dead狀態(tài),他就再也不能進入一個獨立線程的生命周期了。對于一個處于Dead狀態(tài)的線程調用start()方法,會出現(xiàn)一個運行期(runtime exception)的異常;處于Dead狀態(tài)的線程不是活著的(not alive)。

線程狀態(tài)圖

Ø線程的方法(Method)、屬性(PRoperty)

1)優(yōu)先級(priority)

每個類都有自己的優(yōu)先級,一般property用1-10的整數表示,默認優(yōu)先級是5,優(yōu)先級最高是10;優(yōu)先級高的線程并不一定比優(yōu)先級低的線程執(zhí)行的機會高,只是執(zhí)行的機率高;默認一個線程的優(yōu)先級和創(chuàng)建他的線程優(yōu)先級相同;

2)Thread.sleep()/sleep(long millis)

當前線程睡眠/millis的時間(millis指定睡眠時間是其最小的不執(zhí)行時間,因為sleep(millis)休眠到達后,無法保證會被JVM立即調度);sleep()是一個靜態(tài)方法(static method) ,所以他不會停止其他的線程也處于休眠狀態(tài);線程sleep()時不會失去擁有的對象鎖。 作用:保持對象鎖,讓出CPU,調用目的是不讓當前線程獨自霸占該進程所獲取的CPU資源,以留一定的時間給其他線程執(zhí)行的機會;

3)Thread.yield()

讓出CPU的使用權,給其他線程執(zhí)行機會、讓同等優(yōu)先權的線程運行(但并不保證當前線程會被JVM再次調度、使該線程重新進入Running狀態(tài)),如果沒有同等優(yōu)先權的線程,那么yield()方法將不會起作用。

4)thread.join()

使用該方法的線程會在此之間執(zhí)行完畢后再往下繼續(xù)執(zhí)行。

5)object.wait() 當一個線程執(zhí)行到wait()方法時,他就進入到一個和該對象相關的等待池(Waiting Pool)中,同時失去了對象的機鎖—暫時的,wait后還要返還對象鎖。當前線程必須擁有當前對象的鎖,如果當前線程不是此鎖的擁有者,會拋出IllegalMonitorStateException異常,所以wait()必須在synchronized block中調用。sleep()和wait()方法的最大區(qū)別是:sleep()睡眠時,保持對象鎖,仍然占有該鎖;而wait()睡眠時,釋放對象鎖。但是wait()和sleep()都可以通過interrupt()方法打斷線程的暫停狀態(tài),從而使線程立刻拋出InterruptedException(但不建議使用該方法)。

6)object.notify()/notifyAll()

喚醒在當前對象等待池中等待的第一個線程/所有線程。notify()/notifyAll()也必須擁有相同對象鎖,否則也會拋出IllegalMonitorStateException異常。

7)Synchronizing Block

Synchronized Block/方法控制對類成員變量的訪問;Java中的每一個對象都有唯一的一個內置的鎖,每個Synchronized Block/方法只有持有調用該方法被鎖定對象的鎖才可以訪問,否則所屬線程阻塞;機鎖具有獨占性、一旦被一個Thread持有,其他的Thread就不能再擁有(不能訪問其他同步方法),方法一旦執(zhí)行,就獨占該鎖,直到從該方法返回時才將鎖釋放,此后被阻塞的線程方能獲得該鎖,重新進入可執(zhí)行狀態(tài)。正確停止Java線程

  非正確停止的方法:stop()

  要正確停止線程,應該使用正確的退出標記。正常情況下run方法執(zhí)行完畢線程就停止了,但是有些情況下run方法中需要while循環(huán)保持輪詢,所以應該為while循環(huán)設置合適的退出條件,即退出標記,保證線程正確停止。

  或者使用interrupt()方法的初衷并不是要停止線程,正常情況下,調用該方法可以將中斷標記設置為TRUE。但是,當某個線程因為調用了wait()或者sleep()等方法而被阻塞時,此時調用interrupt()方法并不能正確的將interrupted標記設置為TRUE,并且同時會拋出中斷異常。

爭用條件:當多個線程同時共享訪問同一個內存數據時,每個線程都嘗試操作該數據,從而導致數據被破壞。

線程的互斥與同步

互斥是指在同一時刻只有一個線程可以對臨界區(qū)進行操作。在JAVA中,可以通過synchronized塊或者方法來實現(xiàn)。

在synchronized塊中,需要對某個對象進行加鎖,并將需要互斥的代碼放入synchronized塊中,從而來實現(xiàn)互斥行為。獲得該鎖的進程可以進入該synchronized塊中.

而同步則是線程之間的一種通信機制,通過同步可以規(guī)定線程執(zhí)行的順序。例如,當線程不滿足訪問某資源時,可以通過調用鎖對象的lock.wait()方法,使該線程讓出CPU,讓出鎖,并在該鎖對象的waitset中等待。滿足條件時,可以通過lock.notify()方法隨機喚醒一條線程,lock.notifyAll()則喚醒該waitset中所有的線程,使它們重新競爭該鎖。被喚醒的線程從wait()方法處繼續(xù)執(zhí)行。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 太仆寺旗| 连云港市| 永吉县| 思茅市| 茂名市| 东山县| 乐都县| 乌恰县| 安徽省| 五常市| 邹平县| 莱西市| 綦江县| 高密市| 旌德县| 确山县| 淮南市| 紫阳县| 伊川县| 临漳县| 会泽县| 桓台县| 商河县| 紫金县| 子洲县| 西宁市| 司法| 金湖县| 建瓯市| 平和县| 大安市| 延川县| 越西县| 武定县| 湛江市| 平顶山市| 海丰县| 那坡县| 伊宁市| 启东市| 平阴县|