面向对象程序设计(JAVA)复习笔记(下)
文章目錄
- 五、接口和多態(tài)
- 接口
- 塑型
- 多態(tài)
- 內(nèi)部類
- 六、I/O與文件
- 輸入輸出流(java.io)
- 面向字符的流
- 面向字節(jié)的流
- 標(biāo)準(zhǔn)輸入輸出流
- 文件
- 二進(jìn)制文件
- FILE類
- 七、數(shù)組集合
- 對象數(shù)組
- Java集合框架—Collection接口
- Java集合框架—Set、SortedSet接口
- Iterator類
- TreeSet類
- public native int hashCode()
- Java集合框架—List接口
- Java集合框架—Map、SortedMap接口
- 接口的實(shí)現(xiàn)
- 向量
- 集合的遍歷
- 哈希表
- 八、線程
- 多線程編程基礎(chǔ)
- 繼承java.lang包中的Thread類
- 實(shí)現(xiàn)Runnable接口
- 線程間的數(shù)據(jù)共享
- 多線程的同步控制
- 線程之間的通信
- 線程 死鎖
- 避免死鎖
- 后臺線程
- 線程的存活周期
- 控制線程的生命
- 線程的優(yōu)先級
五、接口和多態(tài)
接口
接口
與抽象類一樣都是定義多個(gè)類的共同屬性
使抽象的概念更深入了一層,是一個(gè)“純”抽象類,它只提供一種形式,并不提供實(shí)現(xiàn)
允許創(chuàng)建者規(guī)定方法的基本形式:方法名、參數(shù)列表以及返回類型,但不規(guī)定方法主體
也可以包含基本數(shù)據(jù)類型的數(shù)據(jù)成員,但它們都默認(rèn)為static和final
所有方法都是抽象方法,接口口里面的所有屬性都是常量。
接口的作用
統(tǒng)一開發(fā)標(biāo)準(zhǔn)(規(guī)范)。接口就是定義了一個(gè)標(biāo)準(zhǔn),使用這個(gè)接口的類就是標(biāo)準(zhǔn)的使用者,實(shí)現(xiàn)了這個(gè)接口的類就是這個(gè)標(biāo)準(zhǔn)的實(shí)現(xiàn)者。接口的出現(xiàn),把使用者和實(shí)現(xiàn)者之間的直接聯(lián)系轉(zhuǎn)化為間接聯(lián)系,把強(qiáng)耦合轉(zhuǎn)換為弱耦合,從而實(shí)現(xiàn)解耦的目的。
實(shí)現(xiàn)多繼承,同時(shí)免除C++中的多繼承那樣的復(fù)雜性
抽象類統(tǒng)一開發(fā)標(biāo)準(zhǔn),但是是單繼承
保險(xiǎn)公司的例子
具有車輛保險(xiǎn)、人員保險(xiǎn)、公司保險(xiǎn)等多種保險(xiǎn)業(yè)務(wù),在對外提供服務(wù)方面具有相似性,如都需要計(jì)算保險(xiǎn)費(fèi)(premium)等,因此可聲明一個(gè)Insurable 接口
在UML圖中,實(shí)現(xiàn)接口用帶有空三角形的虛線表示
接口的語法
聲明格式為
[接口修飾符] interface 接口名稱 [extends 父接口名]{…//方法的原型聲明或靜態(tài)常量 }接口的數(shù)據(jù)成員一定要賦初值,且此值將不能再更改,允許省略final關(guān)鍵字
接口中的方法必須是“抽象方法”,不能有方法體,允許省略public及abstract關(guān)鍵字
接口實(shí)例:
接口與匿名內(nèi)部類實(shí)驗(yàn)
接口的實(shí)現(xiàn)
接口不能用new運(yùn)算符直接產(chǎn)生對象,必須利用其特性設(shè)計(jì)新的類,再用新類來創(chuàng)建對象
利用接口設(shè)計(jì)類的過程,稱為接口的實(shí)現(xiàn),使用implements關(guān)鍵字
語法如下
注意:
對象轉(zhuǎn)型
對象可以被轉(zhuǎn)型為其所屬類實(shí)現(xiàn)的接口類型
舉例:
getPolicyNumber、calculatePremium是Insurable接口中聲明的方法
getMileage是Car類新添加的方法,Insurable接口中沒有聲明此方法
多重繼承
Java的設(shè)計(jì)以簡單實(shí)用為導(dǎo)向,不允許一個(gè)類有多個(gè)父類
但允許一個(gè)類可以實(shí)現(xiàn)多個(gè)接口,通過這種機(jī)制可實(shí)現(xiàn)多重繼承
一個(gè)類實(shí)現(xiàn)多個(gè)接口的語法如下
接口的擴(kuò)展
接口的擴(kuò)展
接口可通過擴(kuò)展的技術(shù)派生出新的接口
原來的接口稱為基接口(base interface)或父接口(super interface)
派生出的接口稱為派生接口(derived interface)或子接口(sub interface)
派生接口不僅可以保有父接口的成員,同時(shí)也可加入新成員以滿足實(shí)際問題的需要
實(shí)現(xiàn)接口的類也必須實(shí)現(xiàn)此接口的父接口
接口擴(kuò)展的語法
Shape是父接口,Shape2D與Shape3D是其子接口。Circle類及Rectangle類實(shí)現(xiàn)接口Shape2D,而Box類及Sphere類實(shí)現(xiàn)接口Shape3D
實(shí)例:
運(yùn)行:
塑型
塑型(type-casting)
又稱為類型轉(zhuǎn)換
方式:
塑型的對象包括
基本數(shù)據(jù)類型
引用變量
將對象暫時(shí)當(dāng)成更一般的對象來對待,并不改變其類型 只能被塑型為任何一個(gè)父類類型對象所屬的類實(shí)現(xiàn)的一個(gè)接口被塑型為父類或接口后,再被塑型回其本身所在的類舉例:
隱式(自動)的類型轉(zhuǎn)換
基本數(shù)據(jù)類型
相容類型之間存儲容量低的自動向存儲容量高的類型轉(zhuǎn)換引用變量
被塑型成更一般的類 Employee emp; emp = new Manager(); //將Manager類型的對象直接賦給//Employee類的引用變量,系統(tǒng)會自動將Manage對象塑 //型為Employee類被塑型為對象所屬類實(shí)現(xiàn)的接口類型
Car jetta = new Car(); Insurable item = jetta;顯式(強(qiáng)制)的類型轉(zhuǎn)換
基本數(shù)據(jù)類型
(int)871.34354; // 結(jié)果為 871 (char)65; // 結(jié)果為‘A’ (long)453; // 結(jié)果為453L引用變量:還原為本來的類型
Employee emp; Manager man; emp = new Manager(); man = (Manager)emp; //將emp強(qiáng)制塑型為本來的類型塑型應(yīng)用的場合包括
賦值號右邊的表達(dá)式類型或?qū)ο筠D(zhuǎn)換為左邊的類型
實(shí)參的類型轉(zhuǎn)換為形參的類型
算數(shù)混合運(yùn)算時(shí),不同類型的項(xiàng)轉(zhuǎn)換為相同的類型再進(jìn)行運(yùn)算
字符串連接運(yùn)算時(shí),如果一個(gè)操作數(shù)為字符串,一個(gè)操作數(shù)為數(shù)值型,則會自動將數(shù)值型轉(zhuǎn)換為字符串
當(dāng)一個(gè)類對象被塑型為其父類后,它提供的方法會減少
當(dāng)Manager對象被塑型為Employee之后,它只能接收getName(),getEmployeeNumber()方法,不能接收getSalary()方法
將其塑型為本來的類型后,又能接收getSalary()方法了
如果在塑型前和塑型后的類中都提供了相同的方法,如果將此方法發(fā)送給塑型后的對象,那么系統(tǒng)將會調(diào)用哪一個(gè)類中的方法?
根據(jù)實(shí)際情況有兩種方法查找方式:
實(shí)例方法的查找:
從對象創(chuàng)建時(shí)的類開始,沿類層次向上查找
Manager man = new Manager(); Employee emp1 = new Employee(); Employee emp2 = (Employee)man; emp1.computePay(); // 調(diào)用Employee類中的computePay()方法 man.computePay(); // 調(diào)用Manager類中的computePay()方法 emp2.computePay(); // 調(diào)用Manager類中的computePay()方法
類方法的查找
在引用變量聲明時(shí)所屬的類中進(jìn)行查找
Manager man = new Manager(); Employee emp1 = new Employee(); Employee emp2 = (Employee)man; man.expenseAllowance(); //in Manager emp1.expenseAllowance(); //in Employee emp2.expenseAllowance(); //in Employee!!!多態(tài)
多態(tài)是指不同類型的對象可以響應(yīng)相同的消息,執(zhí)行同一個(gè)行為,會表現(xiàn)出不同的行為特征。
從相同的基類派生出來的多個(gè)類型可被當(dāng)作同一種類型對待,可對這些不同的類型進(jìn)行同樣的處理,由于多態(tài)性,這些不同派生類對象響應(yīng)同一方法時(shí)的行為是有所差別的
例如
所有的Object類的對象都響應(yīng)toString()方法 所有的BankAccount類的對象都響應(yīng)deposit()方法多態(tài)的目的
所有的對象都可被塑型為相同的類型,響應(yīng)相同的消息
使代碼變得簡單且容易理解
使程序具有很好的“擴(kuò)展性”
多態(tài)的常見形式
多態(tài)的前提
一個(gè)例子:
繪圖——直接的方式
希望能夠畫出任意子類型對象的形狀,可以在Shape 類中聲明幾個(gè)繪圖方法,對不同的實(shí)際對象,采用不同的畫法
繪圖——更好的方式(多態(tài))
在每個(gè)子類中都聲明同名的draw()方法
以后繪圖可如下進(jìn)行
Circle屬于Shape的一種,系統(tǒng)會執(zhí)行自動塑型
當(dāng)調(diào)用方法draw時(shí),實(shí)際調(diào)用的是Circle.draw()
在程序運(yùn)行時(shí)才進(jìn)行綁定,接下來介紹綁定的概念
綁定指將一個(gè)方法調(diào)用同一個(gè)方法主體連接到一起
根據(jù)綁定時(shí)期的不同,可分為
一個(gè)例子:
多態(tài)的應(yīng)用
技術(shù)基礎(chǔ)
向上塑型技術(shù):一個(gè)父類的引用變量可以指向不同的子類對象
動態(tài)綁定技術(shù):運(yùn)行時(shí)根據(jù)父類引用變量所指對象的實(shí)際類型執(zhí)行相應(yīng)的子類方法,從而實(shí)現(xiàn)多態(tài)性
構(gòu)造方法與多態(tài)
構(gòu)造方法與其他方法是有區(qū)別的
構(gòu)造方法并不具有多態(tài)性,但仍然非常有必要理解構(gòu)造方法如何在復(fù)雜的分級結(jié)構(gòu)中隨同多態(tài)性一同使用的情況
構(gòu)造方法的調(diào)用順序
在構(gòu)造派生類的時(shí)候,必須能假定基類所有成員都是有效的。
在構(gòu)造方法內(nèi)部,必須保證使用的所有成員都已初始化。
因此唯一的辦法就是首先調(diào)用基類構(gòu)造方法,然后在進(jìn)入派生類構(gòu)造方法之前,初始化所有能夠訪問的成員
構(gòu)造方法中的多態(tài)方法
在構(gòu)造方法內(nèi)調(diào)用準(zhǔn)備構(gòu)造的那個(gè)對象的動態(tài)綁定方法(抽象方法-抽象類/接口)
會調(diào)用位于派生類里的一個(gè)方法
被調(diào)用方法要操縱的成員可能尚未得到正確的初始化
可能造成一些難于發(fā)現(xiàn)的程序錯(cuò)誤
內(nèi)部類
內(nèi)部類
在另一個(gè)類或方法的定義中定義的類
可訪問其外部類中的所有數(shù)據(jù)成員和方法成員
可對邏輯上相互聯(lián)系的類進(jìn)行分組
對于同一個(gè)包中的其他類來說,能夠隱藏
可非常方便地編寫事件驅(qū)動程序
聲明方式
命名的內(nèi)部類:可在類的內(nèi)部多次使用 匿名內(nèi)部類:可在new關(guān)鍵字后聲明內(nèi)部類,立即創(chuàng)建一個(gè)對象假設(shè)外層類名為Myclass,則該類的內(nèi)部類名為
Myclass$c1.class (c1為命名的內(nèi)部類名) Myclass$1.class (表示類中聲明的第一個(gè)匿名內(nèi)部類)內(nèi)部類實(shí)現(xiàn)接口
可以完全不被看到,而且不能被調(diào)用
可以方便實(shí)現(xiàn)“隱藏實(shí)現(xiàn)細(xì)則”。你所能得到的僅僅是指向基類(base class)或者接口的一個(gè)引用
方法中的內(nèi)部類
在方法內(nèi)定義一個(gè)內(nèi)部類
為實(shí)現(xiàn)某個(gè)接口,產(chǎn)生并返回一個(gè)引用
為解決一個(gè)復(fù)雜問題,需要建立一個(gè)類,而又不想它為外界所用
六、I/O與文件
輸入輸出流(java.io)
輸入流
為了從信息源獲取信息,程序打開一個(gè)輸入流,程序可從輸入流讀取信息
輸出流
當(dāng)程序需要向目標(biāo)位置寫信息時(shí),便需要打開一個(gè)輸出流,程序通過輸出流向這個(gè)目標(biāo)位置寫信息
輸入/輸出流可以從以下幾個(gè)方面進(jìn)行分類
從流的方向劃分
從流的分工劃分
節(jié)點(diǎn)流 處理流從流的內(nèi)容劃分
面向字符的流 面向字節(jié)的流面向字符的流:專門用于字符數(shù)據(jù)
面向字節(jié)的流:用于一般目的
面向字符的流
面向字符的流
針對字符數(shù)據(jù)的特點(diǎn)進(jìn)行過優(yōu)化,提供一些面向字符的有用特性
源或目標(biāo)通常是文本文件
面向字符的抽象類——Reader和Writer
java.io包中所有字符流的抽象基類 Reader提供了輸入字符的API Writer提供了輸出字符的API它們的子類又可分為兩大類
節(jié)點(diǎn)流:從數(shù)據(jù)源讀入數(shù)據(jù)或往目的地寫出數(shù)據(jù) 處理流:對數(shù)據(jù)執(zhí)行某種處理多數(shù)程序使用這兩個(gè)抽象類的一系列子類來讀入/寫出文本信息
例如FileReader/FileWriter用來讀/寫文本文件
面向字節(jié)的流
InputStream和OutputStream
是用來處理8位字節(jié)流的抽象基類,程序使用這兩個(gè)類的子類來讀寫8位的字節(jié)信息
分為兩部分
標(biāo)準(zhǔn)輸入輸出流
標(biāo)準(zhǔn)輸入輸出流對象
System類的靜態(tài)成員變量
包括
System.in: InputStream類型的,代表標(biāo)準(zhǔn)輸入流,這個(gè)流是已經(jīng)打開了的,默認(rèn)狀態(tài)對應(yīng)于鍵盤輸入。
System.out:PrintStream類型的,代表標(biāo)準(zhǔn)輸出流,默認(rèn)狀態(tài)對應(yīng)于屏幕輸出
System.err:PrintStream類型的,代表標(biāo)準(zhǔn)錯(cuò)誤信息輸出流,默認(rèn)狀態(tài)對應(yīng)于屏幕輸出
System.in
程序啟動時(shí)由Java系統(tǒng)自動創(chuàng)建的流對象,它是原始的字節(jié)流,不能直接從中讀取字符,需要對其進(jìn)行進(jìn)一步的處理
InputStreamReader(System.in)
以System.in為參數(shù)創(chuàng)建一個(gè)InputStreamReader流對象,相當(dāng)于字節(jié)流和字符流之間的一座橋梁,讀取字節(jié)并將其轉(zhuǎn)換為字符
BufferedReader in
對InputStreamReader處理后的信息進(jìn)行緩沖,以提高效率
IO異常
多數(shù)IO方法在遇到錯(cuò)誤時(shí)會拋出異常,因此調(diào)用這些方法時(shí)必須
在方法頭聲明拋出throws IOException異常
或者在try塊中執(zhí)行IO,然后捕獲catch IOException
文件
在給出 File 對象的情況下構(gòu)造一個(gè) FileWriter 對象。
FileWriter(File file, boolean append)在給出文件名的情況下構(gòu)造 FileWriter 對象,它具有指示是否追加寫入數(shù)據(jù)的 boolean 值。
FileWriter(String fileName, boolean append)方法:
public void write(int c) throws IOException寫入單個(gè)字符c
public void write(char [] c, int offset, int len)寫入字符數(shù)組中開始為offset、長度為len的某一部分
public void write(String s, int offset, int len)寫入字符串中開始為offset、長度為len的某一部分
示例:
實(shí)驗(yàn)6
FileReader類
從文本文件中讀取字符
繼承自Reader抽象類的子類InputStreamReader
BufferedReader類
讀文本文件的緩沖器類
具有readLine()方法,可以對換行符進(jìn)行鑒別,一行一行地讀取輸入流中的內(nèi)容
繼承自Reader
二進(jìn)制文件
示例:
實(shí)驗(yàn)7
FILE類
表示磁盤文件信息
定義了一些與平臺無關(guān)的方法來操縱文件
構(gòu)造文件流可以使用File類的對象作為參數(shù)
類 java.io.File
提供文件與路徑的各種有用信息
并不打開文件,或處理文件內(nèi)容
示例:
上下級文件夾之間使用分隔符分開:
在Windows中分隔符為\,在Unix/Linux中分隔符為/。
跨平臺的目錄分隔符
更專業(yè)的做法是使用File.separatorChar,這個(gè)值就會根據(jù)系統(tǒng)得到的相應(yīng)的分割符。
注意:
如果是使用"“,則需要進(jìn)行轉(zhuǎn)義,寫為”\“才可以,如果是兩個(gè)”“,則寫為”\\"。
本章其余內(nèi)容略,掌握實(shí)驗(yàn)內(nèi)容即可。(我們期考這部分不是重點(diǎn),所以這里就簡寫了不少,需要的請自行參考其他博客)
七、數(shù)組集合
對象數(shù)組
先了解兩種排序:
自然排序和客戶化排序
數(shù)組
在Java提供的存儲及隨機(jī)訪問對象序列的各種方法中,數(shù)組是效率最高的一種
優(yōu)點(diǎn)
數(shù)組知道其元素的類型 編譯時(shí)的類型檢查 大小已知代價(jià)
數(shù)組對象的大小是固定的,在生存期內(nèi)大小不可變對象數(shù)組
數(shù)組元素是類的對象 所有元素具有相同的類型 每個(gè)元素都是一個(gè)對象的引用
集合
把具有相同性質(zhì)的一類東西,匯聚成一個(gè)整體
Java集合不能存放基本數(shù)據(jù)類型,而只能存放對象。
它們被組織在以Collection及Map接口為根的層次結(jié)構(gòu)中,稱為集合框架
集合框架(Java Collections Framework)
為表示和操作集合而規(guī)定的一種統(tǒng)一的標(biāo)準(zhǔn)的體系結(jié)構(gòu)
提供了一些現(xiàn)成的數(shù)據(jù)結(jié)構(gòu)可供使用,程序員可以利用集合框架快速編寫代碼,并獲得優(yōu)良性能
包含三大塊內(nèi)容
集合框架接口
聲明了對各種集合類型執(zhí)行的一般操作
包括Collection、Set、List、SortedSet、Map、SortedMap
Java集合包括三種類型:Set(集),List(列表),Map(映射)
所有Java集合類都位于java.util包中
Java集合框架—Collection接口
Collection接口
聲明時(shí)可以使用一個(gè)參數(shù)類型,即Collection<E> (泛型)
聲明了一組操作成批對象的抽象方法:查詢方法、修改方法
查詢方法
修改方法包括
boolean add(Object obj) – 向集合中增加對象 boolean addAll(Collection<?> c) – 將參數(shù)集合中的所有元素增加到接收者集合中 boolean remove(Object obj) –從集合中刪除對象 boolean removeAll(Collection c) -將參數(shù)集合中的所有元素從接收者集合中刪除 boolean retainAll(Collection c) – 在接收者集合中保留參數(shù)集合中的所有元素,其它元素都刪除 void clear() – 刪除集合中的所有元素Java集合框架—Set、SortedSet接口
Set接口
擴(kuò)展了Collection
禁止重復(fù)的元素,是數(shù)學(xué)中“集合”的抽象
對equals和hashCode操作有更強(qiáng)的約定,如果兩個(gè)Set對象包含同樣的元素,二者便是相等的
實(shí)現(xiàn)它的兩個(gè)主要類是哈希集合(HashSet)及樹集合(TreeSet)
SortedSet接口
一種特殊的Set
其中的元素是升序排列的,還增加了與次序相關(guān)的操作
通常用于存放詞匯表這樣的內(nèi)容
Set的一般用法
Set舉例:
HashSet類
HashSet類按照哈希算法來存取集合中的對象,具有很好的存取和查找性能。
當(dāng)向集合中加入一個(gè)對象時(shí),HashSet會調(diào)用對象的hashCode()方法來獲得哈希碼,然后根據(jù)哈希碼進(jìn)一步計(jì)算出對象在集合中的位置。
Hash,一般翻譯做散列、雜湊,或音譯為哈希,是把任意長度的輸入通過散列算法變換成固定長度的輸出,該輸出就是散列值。
這種轉(zhuǎn)換是一種壓縮映射,也就是,散列值的空間通常遠(yuǎn)小于輸入的空間。
不同的輸入可能會散列成相同的輸出,所以不可能從散列值來確定唯一的輸入值。
Hash算法也被稱為散列算法,Hash算法雖然被稱為算法,但實(shí)際上它更像是一種思想。Hash算法沒有一個(gè)固定的公式,只要符合散列思想的算法都可以被稱為是Hash算法。
可參考:
哈希
Iterator類
Iterable接口:實(shí)現(xiàn)該接口的集合對象支持迭代,可以配合foreach使用。
Iterator:迭代器,提供迭代機(jī)制的對象,具體如何迭代是Iterator接口規(guī)范的。包含三個(gè)方法:hasNext、next、remove。
如果集合中的元素沒有排序,Iterator遍歷集合中元素的順序是任意的,并不一定與集合中加入元素的順序是一致的。
Iterator功能比較簡單,并且只能單向移動:
使用方法iterator()要求容器返回一個(gè)Iterator。第一次調(diào)用Iterator的next()方法時(shí),它返回序列的第一個(gè)元素。注意:iterator()方法屬于java.lang.Iterable接口,被Collection繼承。
使用next()獲得序列中的下一個(gè)元素。
使用hasNext()檢查序列中是否還有元素。
使用remove()將迭代器新返回的元素刪除。
Iterator是Java迭代器最簡單的實(shí)現(xiàn),為List設(shè)計(jì)的ListIterator具有更多的功能,它可以從兩個(gè)方向遍歷List,也可以從List中插入和刪除元素。
TreeSet類
TreeSet類實(shí)現(xiàn)了SortedSet接口,能夠?qū)现械膶ο筮M(jìn)行排序。
當(dāng)向集合中加入一個(gè)對象時(shí),會把它插入到有序的對象集合中。
TreeSet支持兩種排序方式:
默認(rèn)情況下采用自然排序。
自然排序
對于表達(dá)式x.compareTo(y),
如果返回值為0,則表示x和y相等 如果返回值大于0,則表示x大于y 如果返回值小于0,則表示x小于yTreeSet調(diào)用對象的compareTo()方法比較集合中對象的大小,然后進(jìn)行升序排列,這種方式稱為自然排序。
正常是按升序排列,在返回前面加個(gè)負(fù)號就可以降序排列
JDK類庫中實(shí)現(xiàn)了Comparable接口的一些類的排序方式。
使用自然排序時(shí),只能向TreeSet集合中加入同一類型的對象,并且這些對象必須實(shí)現(xiàn)Comparable接口。
客戶化排序
Java.util.Comparator<Type>接口提供具體的排序方式,<Type>指定被比較的對象的類型,Comparator有個(gè)compare(Type x,Type y)方法,用于比較兩個(gè)對象的大小。
compare(x, y)
如果希望TreeSet按照Student對象的name屬性進(jìn)行降序排列,可以先創(chuàng)建一個(gè)實(shí)現(xiàn)Comparator接口的類StudentComparator。
StudentComparator類就是一個(gè)自定義的比較器。
public native int hashCode()
默認(rèn)返回對象的32位jvm內(nèi)存地址。
僅當(dāng)創(chuàng)建某個(gè)“類的散列表”時(shí),該類的hashCode() 才有用(作用是:確定該類的每一個(gè)對象在散列表中的位置;)
其它情況下(例如,創(chuàng)建類的單個(gè)對象,或者創(chuàng)建類的對象數(shù)組等等),類的hashCode() 沒有作用。
散列表指的是:Java集合中本質(zhì)是散列表的類,如HashMap,Hashtable,HashSet。
以HashSet為例,來深入說明hashCode()的作用。
hashCode() 和 equals() 的關(guān)系
Java集合框架—List接口
List接口
擴(kuò)展了Collection接口
可包含重復(fù)元素
元素是有順序的,每個(gè)元素都有一個(gè)index值(從0開始)標(biāo)明元素在列表中的位置
在聲明時(shí)可以帶有一個(gè)參數(shù),即List<E>
四個(gè)主要實(shí)現(xiàn)類
List的排序
List只能對集合中的對象按索引順序排序,如果希望對List中的對象按照其他特定的方式排序,可以借助Comparator接口和Collections類。
Collections類是對Java集合類庫中的輔助類,它提供操縱集合的各種靜態(tài)方法。
sort(List list):對List中的對象進(jìn)行自然排序。
sort(List list,Comparator comparator):對List中的對象進(jìn)行客戶化排序, comparator參數(shù)指定排序方式。
Java集合框架—Map、SortedMap接口
Map接口
不是Collection接口的繼承
用于維護(hù)鍵/值對(key/value pairs)
描述從不重復(fù)的鍵到值的映射,是一個(gè)從關(guān)鍵字到值的映射對象
其中不能有重復(fù)的關(guān)鍵字key,每個(gè)關(guān)鍵字最多能夠映射到一個(gè)值
聲明時(shí)可以帶有兩個(gè)參數(shù),即Map<K, V>,其中K表示關(guān)鍵字的類型,V表示值的類型
SortedMap接口
一種特殊的Map,其中的關(guān)鍵字是升序排列的
與SortedSet對等的Map,通常用于詞典和電話目錄等
在聲明時(shí)可以帶有兩個(gè)參數(shù),即SortedMap<K, V>,其中K表示關(guān)鍵字的類型,V表示值的類型
Map(映射):集合中的每一個(gè)元素包含一對鍵對象和值對象,集合中沒有重復(fù)的鍵對象,值對象可以重復(fù)。
向Map集合中加入元素時(shí),必須提供一對鍵對象和值對象。
Map的兩個(gè)主要實(shí)現(xiàn)類:HashMap和TreeMap。
Map最基本的用法,就是提供類似字典的能力。
在Map中檢索元素時(shí),只要給出鍵對象,就會返回值對象。
HashMap按照哈希算法來存取鍵值對象。
為了保證HashMap能正常工作,和HashSet一樣,要求當(dāng)兩個(gè)鍵對象通過equals()方法比較為true時(shí),這兩個(gè)鍵對象的hashCode()方法的返回的哈希碼也一樣。
Map及Map.Entry詳解
TreeMap實(shí)現(xiàn)了SortedSet接口,能夠?qū)︽I對象進(jìn)行排序。支持自然排序和客戶化排序。
接口的實(shí)現(xiàn)
向量
向量(Vector, ArrayList)
實(shí)現(xiàn)了Collection接口的具體類 能夠存儲任意對象,但通常情況下,這些不同類型的對象都具有相同的父類或接口 不能存儲基本類型(`primitive`)的數(shù)據(jù),除非將這些數(shù)據(jù)包裹在包裹類中 其容量能夠根據(jù)空間需要自動擴(kuò)充 增加元素方法的效率較高,除非空間已滿,在這種情況下,在增加之前需要先擴(kuò)充容量Vector方法是同步的,線程安全
ArrayList方法是非同步的,效率較高
Vector類可以實(shí)現(xiàn)動態(tài)的對象數(shù)組。幾乎與ArrayList相同。
由于Vector在各個(gè)方面都沒有突出的性能,所以現(xiàn)在已經(jīng)不提倡使用。
集合的遍歷
遍歷的四種方式
增強(qiáng)for循環(huán)的遍歷:
哈希表
八、線程
多線程編程基礎(chǔ)
多道程序設(shè)計(jì)
在計(jì)算機(jī)內(nèi)存中同時(shí)存放幾道相互獨(dú)立的程序,使它們在管理程序控制之下,相互穿插地運(yùn)行。 兩個(gè)或兩個(gè)以上程序在計(jì)算機(jī)系統(tǒng)中同處于開始到結(jié)束之間的狀態(tài)。
多道程序技術(shù)運(yùn)行的特征
多道 宏觀上并行 微觀上串行(單核CPU)程序的并發(fā)執(zhí)行
一組在邏輯上互相獨(dú)立的程序或程序段在執(zhí)行過程中其執(zhí)行時(shí)間在客觀上互相重疊,即一個(gè)程序段的執(zhí)行尚未結(jié)束,另一個(gè)程序段的執(zhí)行已經(jīng)開始的執(zhí)行方式。
程序并發(fā)執(zhí)行時(shí)具有如下特征:
間斷性 失去封閉性 不可再現(xiàn)性進(jìn)程的定義
進(jìn)程是一個(gè)具有一定獨(dú)立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合的一次運(yùn)行活動。是操作系統(tǒng)能夠進(jìn)行資源分配的單位。
進(jìn)程的特征
結(jié)構(gòu)特征 動態(tài)性 并發(fā)性 獨(dú)立性 異步性線程的定義
線程(thread)是操作系統(tǒng)能夠進(jìn)行CPU運(yùn)算調(diào)度的最小單位。
它被包含在進(jìn)程之中,是進(jìn)程中的實(shí)際運(yùn)作單位。
一條線程指的是進(jìn)程中一個(gè)單一順序的控制流,一個(gè)進(jìn)程中可以并發(fā)多個(gè)線程,每條線程并行執(zhí)行不同的任務(wù):
進(jìn)程:是并發(fā)執(zhí)行的程序在執(zhí)行過程中分配和管理資源的基本單位,是一個(gè)動態(tài)概念,競爭計(jì)算機(jī)系統(tǒng)資源的基本單位。
線程:是進(jìn)程的一個(gè)執(zhí)行單元,是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位。線程也被稱為輕量級進(jìn)程。
一個(gè)程序至少一個(gè)進(jìn)程,一個(gè)進(jìn)程至少一個(gè)線程。
為什么會有線程?
每個(gè)進(jìn)程都有自己的地址空間,即進(jìn)程空間,在網(wǎng)絡(luò)或多用戶交換機(jī)下,一個(gè)服務(wù)器通常需要接收大量不確定數(shù)量用戶的并發(fā)請求,為每一個(gè)請求都創(chuàng)建一個(gè)進(jìn)程顯然行不通(系統(tǒng)開銷大響應(yīng)用戶請求效率低),因此操作系統(tǒng)中線程概念被引進(jìn)。
進(jìn)程線程的區(qū)別:
線程是處理器調(diào)度的基本單位,但是進(jìn)程不是。
進(jìn)程的3種基本狀態(tài)及其轉(zhuǎn)換
阻塞:
就是程序運(yùn)行到某些函數(shù)或過程后等待某些事件發(fā)生而暫時(shí)停止CPU占用的情況;也就是說,是一種CPU閑等狀態(tài)。
什么情況下考慮使用線程?
使用線程的好處有以下幾點(diǎn):
使用線程可以把占據(jù)長時(shí)間的程序中的任務(wù)放到后臺去處理。
用戶界面可以更加吸引人,這樣比如用戶點(diǎn)擊了一個(gè)按鈕去觸發(fā)某些事件的處理,可以彈出一個(gè)進(jìn)度條來顯示處理的進(jìn)度。
程序的運(yùn)行速度可能加快。
在一些等待的任務(wù)實(shí)現(xiàn)上如用戶輸入、文件讀寫和網(wǎng)絡(luò)收發(fā)數(shù)據(jù)等,線程就比較有用了。在這種情況下可以釋放一些珍貴的資源如內(nèi)存占用等等。
……
示例:
多線程最多的場景:
Web服務(wù)器
各種專用服務(wù)器(如游戲服務(wù)器)
后臺任務(wù),例如:定時(shí)向大量(100w以上)的用戶發(fā)送郵件
異步處理,例如:發(fā)微博、記錄日志等
分布式計(jì)算、高性能計(jì)算
程序、進(jìn)程、線程
程序(Program):是一段靜態(tài)的代碼,它是應(yīng)用軟件執(zhí)行的藍(lán)本。
進(jìn)程(Process):是程序的一次執(zhí)行過程,是系統(tǒng)運(yùn)行程序的基本單位,系統(tǒng)分配管理資源的最小單位。在操作系統(tǒng)中能同時(shí)運(yùn)行多個(gè)任務(wù)(程序);
線程(Thread) :是比進(jìn)程更小的執(zhí)行單位,相當(dāng)于一個(gè)任務(wù)中的一條執(zhí)行路徑,系統(tǒng)運(yùn)算調(diào)度的最小單位。在同一個(gè)應(yīng)用程序中有多個(gè)順序流同時(shí)執(zhí)行。
多線程的目的是為了最大限度的利用CPU資源。
Java中實(shí)現(xiàn)多線程的方法有兩種:
繼承java.lang包中的Thread類
Thread類直接繼承了Object類,并實(shí)現(xiàn)了Runnable接口。位于java.lang包中
封裝了線程對象需要的屬性和方法
繼承Thread類——創(chuàng)建多線程的方法之一
從Thread類派生一個(gè)子類,并創(chuàng)建子類的對象
子類應(yīng)該重寫Thread類的run方法,寫入需要在新線程中執(zhí)行的語句段。
調(diào)用start方法來啟動新線程,自動進(jìn)入run方法。
定義一個(gè)Thread的子類并重寫其run方法如:
class MyThread extends Thread {@Overridepublic void run() {...}}生成該類的對象:
MyThread myThread = new MyThread();啟動或運(yùn)行線程,Java虛擬機(jī)會自動啟動線程,從而由Java虛擬機(jī)進(jìn)一步統(tǒng)一調(diào)度線程,實(shí)現(xiàn)各個(gè)線程一起并發(fā)地運(yùn)行。
public void start() myThread.start();舉例:
public class ThreadCreateDemo1 {public static void main(String[] args) {MyThread thread = new MyThread();thread.start(); //該方法調(diào)用多次,出現(xiàn)IllegalThreadStateException} }class MyThread extends Thread {@Overridepublic void run() {super.run();System.out.println("hellow_world!");} }實(shí)現(xiàn)Runnable接口
Runnable接口
Thread類實(shí)現(xiàn)了Runnable接口
只有一個(gè)run()方法
更便于多個(gè)線程共享資源
Java不支持多繼承,如果已經(jīng)繼承了某個(gè)基類,便需要實(shí)現(xiàn)Runnable接口來生成多線程
以實(shí)現(xiàn)runnable的對象為參數(shù)建立新的線程
start方法啟動線程就會運(yùn)行run()方法
舉例:
public class ThreadCreateDemo2 {public static void main(String[] args) {Runnable runnable = new MyRunnable();Thread thread = new Thread(runnable);thread.start();} }class MyRunnable implements Runnable {public void run() {System.out.println("通過Runnable創(chuàng)建的線程!");} }繼承Thread和實(shí)現(xiàn)Runnable接口的區(qū)別:
a.實(shí)現(xiàn)Runnable接口避免多繼承局限 b.實(shí)現(xiàn)Runnable()可以更好的體現(xiàn)共享的概念線程間的數(shù)據(jù)共享
用同一個(gè)實(shí)現(xiàn)了Runnable接口的對象作為參數(shù)創(chuàng)建多個(gè)線程
多個(gè)線程共享同一對象中的相同的數(shù)據(jù)
獨(dú)立的同時(shí)運(yùn)行的線程有時(shí)需要共享一些數(shù)據(jù)并且考慮到彼此的狀態(tài)和動作。這樣就存在了互相干擾數(shù)據(jù)的問題(共享數(shù)據(jù)錯(cuò)誤)
并發(fā)編程
多線程的同步控制
有時(shí)線程之間彼此不獨(dú)立、需要同步
線程間的互斥
同時(shí)運(yùn)行的幾個(gè)線程需要共享一個(gè)(些)數(shù)據(jù) 共享的數(shù)據(jù),在某一時(shí)刻只允許一個(gè)線程對其進(jìn)行操作“生產(chǎn)者/消費(fèi)者” 問題
假設(shè)有一個(gè)線程負(fù)責(zé)往數(shù)據(jù)區(qū)寫數(shù)據(jù),另一個(gè)線程從同一數(shù)據(jù)區(qū)中讀數(shù)據(jù),兩個(gè)線程可以并行執(zhí)行 如果數(shù)據(jù)區(qū)已滿,生產(chǎn)者要等消費(fèi)者取走一些數(shù)據(jù)后才能再寫 當(dāng)數(shù)據(jù)區(qū)空時(shí),消費(fèi)者要等生產(chǎn)者寫入一些數(shù)據(jù)后再取線程同步Synchronization
互斥:許多線程在同一個(gè)共享數(shù)據(jù)上操作而互不干擾,同一時(shí)刻只能有一個(gè)線程訪問該共享數(shù)據(jù)。因此有些方法或程序段在同一時(shí)刻只能被一個(gè)線程執(zhí)行,稱之為監(jiān)視區(qū)(臨界區(qū))。
協(xié)作:多個(gè)線程可以有條件地同時(shí)操作共享數(shù)據(jù)。執(zhí)行監(jiān)視區(qū)代碼的線程在條件滿足的情況下可以允許其它線程進(jìn)入監(jiān)視區(qū)。
多線程的線程同步機(jī)制實(shí)際上是靠鎖的概念來控制的。
多線程的鎖同步機(jī)制
對象鎖。鎖住對象,不同實(shí)例的鎖互不影響。
類鎖。對象都共用同一把鎖,同步執(zhí)行,一個(gè)線程執(zhí)行結(jié)束、其他對象線程才能夠調(diào)用同步的部分。不同的類鎖互不影響。
對象鎖的兩種形式:(注意synchronized)
public class Test {// 對象鎖:形式1(修飾實(shí)例方法)public synchronized void Method1(){System.out.println("我是對象鎖也是方法鎖");try{Thread.sleep(500);} catch (InterruptedException e){e.printStackTrace();}}// 對象鎖:形式2(修飾代碼塊)public void Method2(){synchronized (this){System.out.println("我是對象鎖");try{Thread.sleep(500);} catch (InterruptedException e){e.printStackTrace();}}}}類鎖:
public class Test {// 類鎖:形式1public static synchronized void Method1(){System.out.println("我是類鎖一號");try{Thread.sleep(500);} catch (InterruptedException e){e.printStackTrace();}}// 類鎖:形式2public void Method2(){synchronized (Test.class){System.out.println("我是類鎖二號");try{Thread.sleep(500);} catch (InterruptedException e){e.printStackTrace();}}} }Java 使用監(jiān)視器機(jī)制
每個(gè)對象只有一個(gè)鎖旗標(biāo) ,利用多線程對鎖旗標(biāo)的爭奪實(shí)現(xiàn)線程間的互斥
當(dāng)線程A獲得了一個(gè)對象的鎖旗標(biāo)后,線程B必須等待線程A完成規(guī)定的操作、并釋放出鎖旗標(biāo)后,才能獲得該對象的鎖旗標(biāo),并執(zhí)行線程B中的操作
將需要互斥的語句段放入synchronized(object){}語句中,且兩處的object是相同的
線程之間的通信
為了更有效地協(xié)調(diào)不同線程的工作,需要在線程間建立溝通渠道,通過線程間的“對話”來解決線程間的同步問題
java.lang.Object 類的一些方法為線程間的通訊提供了有效手段
wait() 如果當(dāng)前狀態(tài)不適合本線程執(zhí)行,正在執(zhí)行同步代碼(synchronized)的某個(gè)線程A調(diào)用該方法(在對象x上),該線程暫停執(zhí)行而進(jìn)入對象x的等待池,并釋放已獲得的對象x的鎖旗標(biāo)。線程A要一直等到其他線程在對象x上調(diào)用notify或notifyAll方法,才能夠再重新獲得對象x的鎖旗標(biāo)后繼續(xù)執(zhí)行(從wait語句后繼續(xù)執(zhí)行)
notify() 隨機(jī)喚醒一個(gè)等待的線程,本線程繼續(xù)執(zhí)行
線程被喚醒以后,還要等發(fā)出喚醒消息者釋放監(jiān)視器,這期間關(guān)鍵數(shù)據(jù)仍可能被改變
被喚醒的線程開始執(zhí)行時(shí),一定要判斷當(dāng)前狀態(tài)是否適合自己運(yùn)行
notifyAll() 喚醒所有等待的線程,本線程繼續(xù)執(zhí)行
wait、notify/notifyAll 詳解
在多線程中要測試某個(gè)條件的變化,使用if 還是while?
顯然,只有當(dāng)前值滿足需要值的時(shí)候,線程才可以往下執(zhí)行,所以,必須使用while 循環(huán)阻塞。注意,wait() 當(dāng)被喚醒時(shí)候,只是讓while循環(huán)繼續(xù)往下走.如果此處用if的話,意味著if繼續(xù)往下走,會跳出if語句塊。但是,notifyAll 只是負(fù)責(zé)喚醒線程,并不保證條件,所以需要手動來保證程序的邏輯。
線程 死鎖
阻塞:暫停一個(gè)線程的執(zhí)行以等待某個(gè)條件發(fā)生。
IO阻塞:
線程阻塞
synchronized(obj)等待obj解鎖; wait(),等待其他線程的notify()。臨界資源
多道程序系統(tǒng)中存在許多進(jìn)程,它們共享各種資源,然而有很多資源一次只能供一個(gè)進(jìn)程使用。一次僅允許一個(gè)進(jìn)程使用的資源稱為臨界資源。許多物理設(shè)備都屬于臨界資源,如輸入機(jī)、打印機(jī)、磁帶機(jī)等。
各進(jìn)程采取互斥的方式,實(shí)現(xiàn)共享的資源稱作臨界資源。
屬于臨界資源的硬件有打印機(jī)、磁帶機(jī)等,軟件有消息緩沖隊(duì)列、變量、數(shù)組、緩沖區(qū)等。
每個(gè)進(jìn)程中訪問臨界資源的那段代碼稱為臨界區(qū)。顯然,若能保證諸進(jìn)程互斥地進(jìn)入自己的臨界區(qū),便可實(shí)現(xiàn)諸進(jìn)程對臨界資源的互斥訪問。
死鎖
多個(gè)線程同時(shí)被阻塞,它們中的一個(gè)或者全部都在等待某個(gè)資源被釋放。由于線程被無限期地阻塞,因此程序不可能正常終止。
四個(gè)必要條件:
互斥使用,即當(dāng)資源被一個(gè)線程使用(占有)時(shí),別的線程不能使用 不可搶占,資源請求者不能強(qiáng)制從資源占有者手中奪取資源,資源只能由資源占有者主動釋放。 請求和保持,即當(dāng)資源請求者在請求其他的資源的同時(shí)保持對原有資源的占有。 循環(huán)等待,即存在一個(gè)等待隊(duì)列:P1占有P2的資源,P2占有P3的資源,P3占有P1的資源。這樣就形成了一個(gè)等待環(huán)路。一個(gè)例子:
避免死鎖
sychronized
信號量Semaphore
一個(gè)計(jì)數(shù)信號量。從概念上講,信號量維護(hù)了一個(gè)許可集。如有必要,在許可可用前會阻塞每一個(gè) acquire(),然后再獲取該許可。每個(gè)release()添加一個(gè)許可,從而可能釋放一個(gè)正在阻塞的獲取者。但是,不使用實(shí)際的許可對象,
Semaphore只對可用許可的號碼進(jìn)行計(jì)數(shù),并采取相應(yīng)的行動。拿到信號量的線程可以進(jìn)入代碼,否則就等待。通過acquire()和release()獲取和釋放訪問許可。
臨界資源:在某一時(shí)刻只能獨(dú)占使用(互斥)、在不同時(shí)刻又允許多人共享的資源。
例子:
公司的銀行賬戶,由公司授權(quán)多人存、取錢,但每次只允許一個(gè)人存取。
手機(jī)等產(chǎn)品,先由生產(chǎn)者生產(chǎn),后才賣給消費(fèi)者,一個(gè)產(chǎn)品不能同時(shí)處于生產(chǎn)和消費(fèi)中。
線程的同步和互斥:處理臨界資源,涉及多線程之間相互協(xié)作(步驟協(xié)調(diào))。
synchronized鎖定方法,猶如對臨界資源加“鎖”,令方法執(zhí)行過程對臨界資源進(jìn)行“同步”(協(xié)同好步驟)操作。
synchronized鎖定臨界資源,語法:
生產(chǎn)者與消費(fèi)者模型
(1)有一個(gè)具有一定容量的存放產(chǎn)品的倉庫。
(2)生產(chǎn)者不斷生產(chǎn)產(chǎn)品,產(chǎn)品保存在倉庫中(產(chǎn)品入倉)。
(3)消費(fèi)者不斷購買倉庫中的產(chǎn)品(產(chǎn)品出倉)。
(4)只有倉庫有空間,生產(chǎn)者才能生產(chǎn),否則只能等待。
(5)只有倉庫存在產(chǎn)品,消費(fèi)者才能購買(消費(fèi))。
在生產(chǎn)者與消費(fèi)者模型中,涉及4個(gè)概念:產(chǎn)品、倉庫、生產(chǎn)者和消費(fèi)者,關(guān)鍵是后3個(gè):
倉庫,是臨界資源,倉庫的產(chǎn)品不能同時(shí)入倉和出倉。 生產(chǎn)者線程:工人。 消費(fèi)者線程:購買產(chǎn)品的人。現(xiàn)實(shí)世界中,許多問題都可歸結(jié)為生產(chǎn)者與消費(fèi)者模型,比如公司銀行賬戶的存取款操作,銀行賬戶相當(dāng)于一個(gè)海量倉庫,生產(chǎn)(存款)能力沒有限制。
后臺線程
后臺線程
也叫守護(hù)線程,通常是為了輔助其它線程而運(yùn)行的線程
它不妨礙程序終止
一個(gè)進(jìn)程中只要還有一個(gè)前臺線程在運(yùn)行,這個(gè)進(jìn)程就不會結(jié)束;如果一個(gè)進(jìn)程中的所有前臺線程都已經(jīng)結(jié)束,那么無論是否還有未結(jié)束的后臺線程,這個(gè)進(jìn)程都會結(jié)束
“垃圾回收”便是一個(gè)后臺線程
如果對某個(gè)線程對象在啟動(調(diào)用start方法)之前調(diào)用了setDaemon(true)方法,這個(gè)線程就變成了后臺線程
Java中有兩類線程:User Thread(用戶線程)、Daemon Thread(守護(hù)線程)
用戶線程:運(yùn)行在前臺的線程,也叫普通線程,只完成用戶自己想要完成的任務(wù),不提供公共服務(wù)。
創(chuàng)建一個(gè)無限循環(huán)的后臺線程,驗(yàn)證主線程結(jié)束后,程序結(jié)束
運(yùn)行程序,則發(fā)現(xiàn)整個(gè)程序在主線程結(jié)束時(shí)就隨之中止運(yùn)行了,如果注釋掉t.setDaemon(true)語句,則程序永遠(yuǎn)不會結(jié)束
線程的存活周期
線程的生命周期
線程從產(chǎn)生到消亡的過程
一個(gè)線程在任何時(shí)刻都處于某種線程狀態(tài)(thread state)
控制線程的生命
結(jié)束線程的生命
用stop方法可以結(jié)束線程的生命
但如果一個(gè)線程正在操作共享數(shù)據(jù)段,操作過程沒有完成就用stop結(jié)束的話,將會導(dǎo)致數(shù)據(jù)的不完整,因此并不提倡使用此方法
通常,可通過控制run方法中循環(huán)條件的方式來結(jié)束一個(gè)線程
線程的優(yōu)先級
線程調(diào)度
在單CPU的系統(tǒng)中,多個(gè)線程需要共享CPU,在任何時(shí)間點(diǎn)上實(shí)際只能有一個(gè)線程在運(yùn)行
控制多個(gè)線程在同一個(gè)CPU上以某種順序運(yùn)行稱為線程調(diào)度
Java虛擬機(jī)支持一種非常簡單的、確定的調(diào)度算法,叫做固定優(yōu)先級算法。這個(gè)算法基于線程的優(yōu)先級對其進(jìn)行調(diào)度
線程的優(yōu)先級
每個(gè)Java線程都有一個(gè)優(yōu)先級,其范圍都在1和10之間。默認(rèn)情況下,每個(gè)線程的優(yōu)先級都設(shè)置為5
在線程A運(yùn)行過程中創(chuàng)建的新的線程對象B,初始狀態(tài)具有和線程A相同的優(yōu)先級
如果A是個(gè)后臺線程,則B也是個(gè)后臺線程
可在線程創(chuàng)建之后的任何時(shí)候,通過setPriority(int priority)方法改變其原來的優(yōu)先級
基于線程優(yōu)先級的線程調(diào)度
具有較高優(yōu)先級的線程比優(yōu)先級較低的線程優(yōu)先執(zhí)行
對具有相同優(yōu)先級的線程,Java的處理是隨機(jī)的
底層操作系統(tǒng)支持的優(yōu)先級可能要少于10個(gè),這樣會造成一些混亂。因此,只能將優(yōu)先級作為一種很粗略的工具使用。最后的控制可以通過明智地使用yield()函數(shù)來完成
我們只能基于效率的考慮來使用線程優(yōu)先級,而不能依靠線程優(yōu)先級來保證算法的正確性
假設(shè)某線程正在運(yùn)行,則只有出現(xiàn)以下情況之一,才會使其暫停運(yùn)行
總結(jié)
以上是生活随笔為你收集整理的面向对象程序设计(JAVA)复习笔记(下)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iOS7
- 下一篇: 键盘输入 kbhit()