7.16
String類?
String類表示的字符串饶火,但是它屬于一個類坐求,而不是基本數(shù)據(jù)類型絮重,雖然像基本數(shù)據(jù)類型一樣使用
兩種實例化方式惋啃;
第一種方式:String str=”hello ”;
第二種方式:String str=new String(“hello”);
==表達(dá)式比較的是內(nèi)存地址
想要判斷兩個字符串的內(nèi)容是否相等可以使用String類中提供 equals()方法來完成
通過實例化方式完成的String類賦值 默認(rèn)不支持常量池,但是可以通過intern()方法手動入池
字符串常量就是String的匿名對象
String實例化方式賦值的時候會存在兩個對象 其中一個String類型的匿名對象做為垃圾空間存在
????? .java文件編譯.class文件后 字符串類型的類型進(jìn)入常量池中毅该,
倘若String str = new String(“helloword”);則在常量池中生成一個helloword 但是new會開辟一個新的內(nèi)存空間 而常量池的那個作為匿名垃圾對象存在知押;
字符串的內(nèi)容一旦聲明則不可改變
Stirng不可變性
String類常用方法
?public int length()
2 public boolean isEmpty(); 判斷字符串是否為空
3 ?public char charAt(int index);給定索引 反回索引的char字符
4 public byte[] getBytes()鹃骂; 把一個字符串轉(zhuǎn)換為byte[]數(shù)組
5 ?public boolean equals(Object anObject);判斷兩個字符串的內(nèi)容是否相等
6 public boolean equalsIgnoreCase(String anotherString)罢绽; 判斷兩個字符串內(nèi)容是否相等 忽略大小寫
7 public boolean startsWith(String prefix);判斷字符串是否以某個字符串開頭
8 public boolean endsWith(String suffix);判斷字符串是否以某個字符串結(jié)尾
9 public int indexOf(int ch) ??public int indexOf(String str);從前往后找
10 ?public int lastIndexOf(int ch)畏线; ?從后往前找
11 ?public String substring(int beginIndex) ;
12 ??public String concat(String str) ;拼接字符串
13 ?public boolean contains(CharSequence s);判斷一個字符串是否存在
14 ?public String trim();去掉字符串的左右空格
15 ?public char[] toCharArray();把一個字符串變?yōu)樽址麛?shù)組
16 ??public static String valueOf(Object obj)把一個數(shù)據(jù)類型轉(zhuǎn)換為一個字符串
17 ?split()分割字符串
String構(gòu)造方法
1把字符數(shù)組準(zhǔn)換為 字符串
????? ? ? String str =new String(字符數(shù)組數(shù)據(jù)類型/ 字節(jié)數(shù)組的數(shù)據(jù)類型)
2把byte數(shù)組轉(zhuǎn)換為字符串
????????? byte[] data=str.getBytes(); //轉(zhuǎn)換為字節(jié)數(shù)組
????????? String str1=new String(data,0,data.length); //又轉(zhuǎn)換會字符串
this關(guān)鍵字
三個作用
?????????????? 1可以調(diào)用本類屬性
?????????????? 2調(diào)用本類方法
?????????????? 3代表當(dāng)前對象
繼承:
繼承的概念良价,在已有代碼的基礎(chǔ)上寝殴,進(jìn)行擴(kuò)展,可以不用編寫重復(fù)的代碼明垢,父類更抽象蚣常,子類更具體被繼承的類叫做父類,繼承的類叫做子類
方法覆寫的意義:
? 更具體的實現(xiàn)父類制定的標(biāo)準(zhǔn)
方法名稱參數(shù)類型與個數(shù)和返回值和父類完全相同覆寫的方法訪問權(quán)限不能比父類更嚴(yán)格
繼承的限制:
限制1在繼承關(guān)系中只能存在單繼承痊银, (不能多層繼承 但是可以多重繼承)
7.17
1 this與 super關(guān)鍵字的區(qū)別抵蚊?
?????????? This代表本類對象, 調(diào)用本類屬性 ?本類方法
??????????? Super可以調(diào)用父類屬性 和方法 但是不能代表父類對象
2代碼塊
??????? 普通塊
??????? 構(gòu)造快
??????? 靜態(tài)塊
多態(tài):
?????????? 方法的多態(tài):
????????????????? 方法的重載' 覆寫
方法的重載與方法的覆寫的區(qū)別溯革?
方法的重載:方法名稱相同參數(shù)的類型與個數(shù)不同與返回值無關(guān)
方法覆寫:方法名稱參數(shù)類型與個數(shù)和返回值和父類完全相同覆寫的方法訪問權(quán)限不能比父類更嚴(yán)格
???????????? 對象的多態(tài):
向上轉(zhuǎn)型統(tǒng)一標(biāo)準(zhǔn)贞绳,使用的方法向父類對齊
向下轉(zhuǎn)型子類可以使用自己獨特的方法
抽象類與接口的區(qū)別?
抽象類與接口的繼承實現(xiàn)關(guān)系
包裝類
在java的設(shè)計原則中致稀,一切皆對象冈闭,但是程序中的基本數(shù)據(jù)類型是對象嗎?例如 int ?double lang ?char ?
public static void main(String[]args){
???????? //Int n=new Int(1); ?//把一個基本數(shù)據(jù)類型 變?yōu)榱艘脭?shù)據(jù)類型 ?//裝箱
???????? //System.out.println(n.intValue()); ?//把一個類變?yōu)榱?基本數(shù)據(jù)類型 //拆箱
????????? Integer ?n=new Integer(5); ?//裝箱
????????? System.out.println(n.intValue()); ?//拆箱
?????????? Integer n=5; ???//把一個基本數(shù)據(jù)類型 變?yōu)橐粋€類 自動裝箱
?????????? System.out.println(n); //自動拆箱 把一個類變?yōu)橐粋€基本數(shù)據(jù)類型輸出
}
在包裝類中也存在了對象池的概念
數(shù)據(jù)轉(zhuǎn)型:
包裝類的優(yōu)點在于可以編寫操作方法抖单,其中有一個方法為可以把一個字符串變?yōu)榛緮?shù)據(jù)類型來使用
Integer類public static intparseInt(Stirng s) ; //把一個字符串變?yōu)閕nt類型
Double類public static double parseDouble(String s)
Boolean ?public static boolean parseBoolean(String s)
在進(jìn)行數(shù)據(jù)類型轉(zhuǎn)換的時候必須給定轉(zhuǎn)換的內(nèi)容為(正確內(nèi)容)如果給定的內(nèi)容不是轉(zhuǎn)換類型能接收的內(nèi)容則會產(chǎn)生NumberFormatException異常
任何的數(shù)據(jù)類型和String操作都會向String靠攏
想把一個基本數(shù)據(jù)類型轉(zhuǎn)換String類型則有兩種方式
1拼接字符串
2使用String中的valueOf()方法完成
int?n=5;
String str=String.valueOf(n);
System.out.println(str);
異常的處理
什么是異常萎攒?
異常導(dǎo)致程序中斷一種指令流
如果發(fā)現(xiàn)程序異常則后面代碼不在執(zhí)行
處理異常
try{
(break/return)//不管這里是 break 或者是return? finally永遠(yuǎn)執(zhí)行
}catch(異常的類型 異常的對象){
處理異常 //? 越是父類的異常越在下面? 例如 exception放在最上面的catch后? //面會報錯
}finally{// 作用? 關(guān)閉資源 連接數(shù)據(jù)庫
永遠(yuǎn)執(zhí)行的代碼
}jvm創(chuàng)建對象
在異常的繼承結(jié)構(gòu)中最大的父類為Throwable它下面存在兩個子類(面試題)
Error表示 JVM程序出錯遇八, 虛擬機(jī)的層面上出錯,Error是不能被異常處理的
Exception屬于程序中的異常耍休, 是可以被處理的
Exception繼承結(jié)構(gòu)中又分為兩種異常 一種是運行時異常刃永, 一種為普通的異常?
所謂運行時異常就是RunTimeException的子類 特點:在編譯的時候不強(qiáng)制處理異常
(面試題)寫出三個常見運行時異常:
NullPointException NumberFormatException IndexOutOfBoundsException
普通的異常特點:
在編譯階段必須強(qiáng)制處理或者拋出該異常
Throws關(guān)鍵字
定義在方法上使用羹应,表示出現(xiàn)了異常暫不處理交給方法調(diào)用處處理
public?static?int?sum(int?y,int?n)throws?ArithmeticException{
??????????? return?y/n;
}
Throw 關(guān)鍵字
其實所有的異常都是JVM進(jìn)行實例化的揽碘,手動拋出一個異常的則必須使用new關(guān)鍵字完成
try?{
throw?new?Exception("瞎拋的,管不著你"); ?//手動拋出的異常
} catch?(Exception e) {
// TODO?Auto-generated catch block
e.printStackTrace();
}
自定義異常
雖然java中提供了大量的異常园匹,但是可能這些異常都不滿足開發(fā)者的需求雳刺,可以自己編寫異常類
范例:編寫一個自定義異常,一個類繼承了Exception類這個類就可以作為一個異常類
package?org.wubo.test;
public?class?MyException?extends?Exception{ //自定義異常類
public?MyException(String str) {super(str);}}
包的訪問權(quán)限:
在程序中的目的就是為文件進(jìn)行分離裸违,相當(dāng)于操作系統(tǒng)中文件夾掖桦,在程序開發(fā)中肯定代碼不是由一個人完成的
定義包的關(guān)鍵字packeg
命名命名規(guī)范
一般來說就是公司域名的反寫
www.oracle.com包名稱com.oracle.項目名稱
Java中常用的包 (JDK提供的)
Java.lang程序的基本包 這個java.lang屬于自動導(dǎo)入
Java.util 提供的工具類,常用日期集合操作類都在這個包里面
Java.text 文本類
Java.io ?Input ?Output 輸入與輸出
Java.sql數(shù)據(jù)庫支持包
Java.net網(wǎng)絡(luò)編程 soket
以下兩個包接觸不到
Java.awt 重量級圖形界面
Java.swing輕量級圖形界面
7.18
常用類庫
StringBuilder
可以頻繁修改字符串供汛,在實際使用中枪汪,一般來說首選使用String來完成,只有在需要頻繁小修改字符串的時候才使用StringBuilder 后者StringBuffer
以上兩個類除了線程的安全性之外怔昨,其他的功能全部一樣
public?static?void?main(String[] args) {
String str="hello";
? changeStr(str);
? System.out.println(str);
}
public?static?void?changeStr(StringBuilder str) {
str+="word";
}
str只有改變指向才會變
RunTime類
RunTime屬于運行時的操作類雀久,也是JVM運行時需要加載的類
RunTime類的方法
public?native?long?totalMemory();取得總共的可用內(nèi)存
?public?native?long?maxMemory();?取得最大可用內(nèi)存
public?native?long?freeMemory();?取得空閑內(nèi)存
public?native?void?gc();?調(diào)用垃圾收集器,釋放內(nèi)存空間
范例:通過RunTime類取得JVM內(nèi)存信息
System類
在程序以開始輸出的時候就已經(jīng)在使用這個類趁舀,屬于系統(tǒng)類
System.out輸出
System.err錯誤的輸出
System.in輸入
System類常用的方法
public?static?native?void?arraycopy(Object src, ?int??srcPos,
????????????????????????????????????????Object dest, int?destPos,
????????????????????????????????????????int?length);
數(shù)組拷貝
Object src源數(shù)組 ?int srcPos 原數(shù)組開始拷貝的位置 Object desc目標(biāo)數(shù)組 ?int destPos目標(biāo)數(shù)組的開始位置 ?int length長度
int?arr1[]=new?int[] {1,2,3,4,5};
int?arr2[]=new?int[10];
System.arraycopy(arr1, 0, arr2, 0, arr1.length);
public?static?native?long?currentTimeMillis();取得當(dāng)前的系統(tǒng)時間
范例:取得當(dāng)前的系統(tǒng)時間
long?currentTime=System.currentTimeMillis(); //取得當(dāng)前的時間
System.out.println(currentTime);
Date date=new?Date(currentTime);
System.out.println(date);
import?java.util.Date;
public?class?SystemDemo {
public?static?void?main(String[] args) {
long?start=System.currentTimeMillis(); //取得當(dāng)前的時間
String str="";
for(int?i=0;i<10000;i++) {
str+="hello world";
}
long?end=System.currentTimeMillis(); //獲得結(jié)束時間
System.out.println("時間:"+(end-start)+"ms");
}
}
Finlize 作用
對象在創(chuàng)建的時候赖捌,存在構(gòu)造方法表示對象屬性的初始化
package?org.wubo.test;
import?java.util.Date;
public?class?SystemDemo {
public?static?void?main(String[] args) {
Person ?per=new?Person();
per=null;//指向改變成為垃圾對象gc回收相當(dāng)于c++的析構(gòu)函數(shù)
System.gc();
}
}
class?Person{
public?Person() {
System.out.println("出生了 地動山搖 滿天烏云 代表妖孽出生了");
}
@Override
public?void?finalize() throws?Throwable {
// TODO?Auto-generated method stub
System.out.println("我真的還想在活500年");
}
}
日期類Date
主要掌握Date類與long類型相互轉(zhuǎn)換的操作
Public Date(); ?獲取的當(dāng)前時間
Pubic Date(long time)把long類型的時間轉(zhuǎn)換為Date類型
Public long getTime() 把Date類型的時間轉(zhuǎn)換為long類型
日期格式化類
SimpleDateFormat ?java.text
對于SimpleDateFormat只有兩種操作
第一種
把Date類型格式化為字符串類型 ,格式化的格式由用戶給定
SimpleDateFormat sd=new?SimpleDateFormat("yyyy-MM-dd:HH:mm:ss");
String d=sd.format(date);
第二種
把字符串日期格式轉(zhuǎn)換為Date類型格式
String d=sd.format(date);
隨機(jī)數(shù)類
Random ?主要目的產(chǎn)生隨機(jī)數(shù)
?AtomicLong?原子數(shù)據(jù)
public?static?void?main(String[] args) {
Random ran=new?Random();
for(int?i=0;i<10;i++) {
System.out.println(ran.nextInt(100)); ?//輸出0~10范圍內(nèi)的隨機(jī)數(shù) 輸出10次}}
public?static?void?main(String[] args) {
????UUID uid=UUID.randomUUID();//4b96f005-b9b1-42e8-a989-b45a42123099
????System.out.println(uid);}
Math類
java為用戶提供的一些數(shù)學(xué)操作類矮烹,其中四舍五入的操作以及PI的定義
public?static?void?main(String[] args) {
???System.out.println(Math.round(15.5)); //16
???System.out.println(Math.round(-15.6)); //-16
???System.out.println(Math.PI);
}
大數(shù)字操作類
package?org.wubo.test;
import?java.math.BigInteger;
import?java.util.Random;
import?java.util.UUID;
public?class?RandomTest {
public?static?void?main(String[] args) {
????int?max=Integer.MAX_VALUE;
????System.out.println(max);
????BigInteger bigA=new?BigInteger(max+"");
????BigInteger bigb=new?BigInteger(max+"");
????System.out.println( bigA.add(bigb)); //兩個大整數(shù)相加
????System.out.println(bigA.subtract(bigb)); ?//兩個大整數(shù)相減的方法
????System.out.println(bigA.multiply(bigb)); //兩個大整數(shù)相乘
????System.out.println(bigA.divide(bigb)); ?//相除
}
}
Arrays類
數(shù)組的工具類越庇,提供了一系列的數(shù)組相關(guān)的操作方法
Arrays類中提供的方法
BinarySearch()二分查找
int[]arr=new?int[]{1,2,3,4,5,6,7,8,9};
?int?key=Arrays.binarySearch(arr, 3);
?System.out.println(key);
toSting()理解該方法
幾個易混淆的使用方法
1?? String.valueOf();返回值:string
--調(diào)用者:string字符串
--被調(diào)用者 ?:任何對象,任何數(shù)組奉狈,任何類型(前提有tostring方法)
--作用 :將被調(diào)用者以字符串的形式輸出
?? 2.?? Arrays.tostring();返回值:string
--調(diào)用者:Arrays
--被調(diào)用者:存儲著任何對象的數(shù)組卤唉,對象要自帶tostring方法
--作用:將數(shù)組中的對象按照對象的tostring方法一個一個輸出來
?? 3.? 對象.tostring();返回值:string
--調(diào)用者:各種對象
--沒有被調(diào)用對象,直接使用方法
--作用:若對象自定義了tostring方法仁期,那么按照對象定義的方法輸出桑驱,若是對象沒有重寫方法,則按照輸出哈希值
Fill();給定數(shù)組 為其填充內(nèi)容
int[]arr=new?int[10];
Arrays.fill(arr, 20);
for(int?i=0;i
System.out.println(arr[i]);
}
數(shù)組的比較
使用Arrays.equals進(jìn)行數(shù)組的排序
int[]arr=new?int[] {1,2,3};
int[]arr2=new?int[] {1,2,3};
boolean?flag=Arrays.equals(arr, arr2);
對象數(shù)組排序
通過比較器進(jìn)行排序
Comparable? 重寫compareTo方法
@Override
public?int?compareTo(Object o) { ?//該方法只需要反回3個值 0 -1 ?1
// TODO?Auto-generated method stub
Person p=null;
if(o?instanceof?Person) {
p=(Person)o;
}
if(this.age>p.age) {
return?1;
}else?if(this.age
return?-1;
}
return?0;
}
Comparator重寫compare
@Override
public int compare(Person2 p1,Person2 p2) {
if (p1.getAge()>p2.getAge()) {
return 1;
}else if (p1.getAge()
return -1;
}
return 0;
}
7.20 -7.21
1 進(jìn)程與線程的區(qū)別
進(jìn)程:在操作系統(tǒng)的定義中指的是一次命令完整運行
2進(jìn)程與線程的區(qū)別跛蛋?
線程是在進(jìn)程的基礎(chǔ)上上進(jìn)一步劃分:打開一個QQ.exe代表啟動一個進(jìn)程碰纬,在QQ可以聊天,聊天的同時可以傳輸文件问芬,并且還可以語音聊天 在一個QQ進(jìn)程中啟動多個線程
例如:打開一個QQ啟動一個進(jìn)程悦析,在QQ上打開聊天 啟動一個線程,在打開一個傳輸數(shù)據(jù)此衅,又啟動一個線程
從以上的結(jié)論中可以發(fā)現(xiàn)强戴;在一個進(jìn)程中可以存在多個線程:而線程是可以同時運行的
3多線程的優(yōu)點:
效率高:可以最大限度的利用CPU的空閑資源,比如一邊編輯文檔亭螟,一邊打印文檔中的內(nèi)容
4 如何使用多線程
在java中存在兩種方式可以完成多線程的使用,第一種方式就是 (繼承)Thread類 骑歹,在java中編寫多線程程序的時候必須存在一個線程的主體類预烙,而這個主體類只要繼承了Thread類就可以完成多線程的功能
使用了start()方法啟動了多線程之后,發(fā)現(xiàn)定義的3個線程在執(zhí)行的時候 不是順序執(zhí)行了道媚,而是隨機(jī)的訪問CPU的資源扁掸,過程為哪個線程先搶到資源哪個線程就先執(zhí)行 線程的執(zhí)行是存在隨機(jī)性的
在主體方法main方法中把復(fù)雜的任務(wù)2作為一個單獨的線程啟動,這樣就不會影響任務(wù)1 月任務(wù)3 的執(zhí)行效率
通過觀察start()方法的源碼發(fā)現(xiàn):
同一個實例的線程只能啟動一次最域,如果啟動超過一次則會拋出異常IllegalThreadStateException()
繼續(xù)觀察源碼發(fā)現(xiàn)start()方法會調(diào)用一個start0()這個方法而這個方法的定義如下
private?native?void?start0();
其中出現(xiàn)了native關(guān)鍵字谴分,表示調(diào)用本地系統(tǒng)函數(shù)
原理如下:
在線程啟動的時候,線程會搶占CPU的資源镀脂,CPU的資源調(diào)度牺蹄,需要本地操作系統(tǒng)的支持
以上圖一定要明白清楚的自己的可以畫出來,面試過程中會存在為什么啟動一個線程調(diào)用是start()方法而不是run()方法
線程的第二種實現(xiàn)方式實現(xiàn)Runnable接口
為什么存在第二種方式薄翅,第一種方式繼承Thread類有什么不好
最大的問題:java中存在單繼承局限沙兰,如果一個類繼承了Thread類則這個類就沒有辦法繼承別的類
所以為了解決以上的問題,可以使用第二種方式翘魄,實現(xiàn)Runnable接口鼎天,在接口中沒有單繼承的局限,一個類可以實現(xiàn)多個接口
觀察Thread類的構(gòu)造方法可以發(fā)現(xiàn) 構(gòu)造方法的參數(shù)為Runnable接口對象暑竟,也就是說Thread類的構(gòu)造方法可以接收Runnble接口的對象
在多態(tài)中講過训措,在接口中一個父接口可以接收所有的子類對象
例如Runable run=new MyThread();應(yīng)為MyThread類實現(xiàn)了Runnable接口作為Runnable接口的子類 則可以通過構(gòu)造方法傳入給Thread類
通過以上的操作就可以把MyThread傳入給Thread類 進(jìn)而通過Thread類中的start()方法啟動一個線程
注意:無論何時啟動一個線程必須使用Thread類中的start()方法
Thread類與Runnable接口的關(guān)系
在多線程的實現(xiàn)中現(xiàn)在已經(jīng)了兩種方式,Thread類與Runnable接口,從代碼上來講肯定首選使用Runnable接口光羞,應(yīng)為可以很好的避免單繼承局限,可以為程序做更多的擴(kuò)展
通過源碼分析過其實Thread類也是實現(xiàn)的Runnable接口,接下來觀察一下他們兩個的關(guān)系
多線程開發(fā)的本質(zhì)其實就是多個線程同時對一個資源的搶占,Thread主要描述的就是線程怀大,資源是通過Runnable接口完成的
擴(kuò)展:Lambda表達(dá)式
利用Lmbda可以簡化在面向?qū)ο筮^程中的開發(fā)纱兑,但是前提是只有一個抽象方法的接口或者類才可以使用
Lambda表達(dá)式是JDK1.8的新特性,利用此形式可以實現(xiàn)函數(shù)式編程(一個接口或者一個類只存在一個抽象方法) 前提下就可以簡化編寫方式
Scala 語言中就提供了函數(shù)式編程
在面上對象過程中化借,一直存在的問題潜慎,即使編寫簡單的代碼,同樣需要進(jìn)行類的完整定義
public?interface?IMessage {
// 只存在一個抽象方法
public?void?send(String str);
}
public?static?void?main(String[] args) {
IMessage msg=(str)->{
System.out.println("發(fā)送消息"+str);
};
msg.send("hello");
}
對于Lmbda表達(dá)式提供了幾個格式如下:
1 方法沒有參數(shù):()->{};
?2 方法有參數(shù):(參數(shù)1,參數(shù)2)->{};
3 Thread thread =new Thread(()->{});
線程第三種實現(xiàn)方式實現(xiàn)Callable接口
從傳統(tǒng)的開發(fā)角度上來說實現(xiàn)一個多線程肯定使用Runnable接口蓖康,但是Runnable接口有一個缺點:沒有返回值
在Jdk1.5之后推出了callable接口可以給一個線程執(zhí)行完畢反回結(jié)果,接下來觀察callableji接口的定義
Public interface callable
在callable接口內(nèi)設(shè)置了一個泛型操作铐炫,其實這個泛型就是規(guī)定了需要反回的數(shù)據(jù)類型
有這個泛型的支持就不會造成向下轉(zhuǎn)型出現(xiàn)錯誤
public?class?MyThread implements?Callable{
@Override
public?String call() throws?Exception {
// TODO?Auto-generated method stub
//實現(xiàn)線程的業(yè)務(wù)方法 類似run方法
for(int?i=0;i<10;i++) {
System.out.println("線程執(zhí)行i="+i);
}
return?"執(zhí)行完畢"; //與run方法不同的是存在了返回值
}}
package?org.callable.demo;
import?java.util.concurrent.ExecutionException;
import?java.util.concurrent.FutureTask;
public?class?ThreadTest {
public?static?void?main(String[] args) throws?InterruptedException, ExecutionException {
FutureTask task=new?FutureTask<>(new?MyThread());
new?Thread(task).start();
//通過Thread啟動線程之后 可以通過FutureTask存在get方法可以取得call()方法中的返回值
String result=task.get();
System.out.println(result);
}
}
面試題:Callable接口 與Runnable接口的區(qū)別?
Runnable接口沒有返回值蒜焊, Callable接口可以在執(zhí)行多線程任務(wù)之后返回數(shù)據(jù)類型
線程的狀態(tài):(面試題)
(面試題)
1 任何一個線程對象都是通過Thread類進(jìn)行封裝倒信,調(diào)用start()方法進(jìn)入到就緒狀態(tài),就緒狀態(tài)線程并沒有執(zhí)行
2線程進(jìn)入到就緒狀態(tài)之后,等到資源調(diào)度泳梆,搶到資源的線程先執(zhí)行鳖悠,先執(zhí)行的線程就進(jìn)入到運行狀態(tài)
3 線程在執(zhí)行的過程可能會存在阻塞狀態(tài)榜掌,當(dāng)用戶調(diào)用類似sleep或者wait?方法會進(jìn)入到阻塞狀態(tài)
4終止?fàn)顟B(tài),當(dāng)線程執(zhí)行完畢乘综,或者調(diào)用線程的停止的方法線程就會進(jìn)入到終止?fàn)顟B(tài)
線程的常用操作方法:
所有線程的操作方法基本上都定義在Thread類中
1線程的命名與取得
線程的運行狀態(tài)是不確定憎账,如果在不確定的線程中操作一個線程只能依靠線程的名字,線程的名字是非常重要的概念,在Thread方法中提供有線程的命名與取得的方法
1構(gòu)造方法: public Thread(Stirng name);
2 public final String getName(); 取得線程的名稱
3 public final void setName(String name); 設(shè)置線程名稱
通過以上的三個方法可以完成線程的命名與取得卡辰,但是并不能通過以上方法取得線程當(dāng)前的對象
Thread類中提供了?
1取得當(dāng)前線程的方法 public static Thread currentThread();
為線程設(shè)置名稱和取得名稱在以上的代碼中直接在main方法輸出當(dāng)前線程的名稱輸出為main說明main方法也是一個線程 在JVM啟動的時候會啟動兩個線程一個是main方法另一個是GC
public?class?RunnableDemo03 {
public?static?void?main(String[] args) {
// 為線程命名
MyThread03 mt=new?MyThread03();
Thread t1=new?Thread(mt);
t1.setName("線程A");
t1.start();
System.out.println(Thread.currentThread().getName());
}
}
2線程的休眠
public?static?native?void?sleep(long?millis) throws?InterruptedException;
如果現(xiàn)在希望一個程序跑的慢一點,或者說暫緩執(zhí)行胞皱,可以使用Thread類中提供的sleep()方
完成
該方法需要的參數(shù)long類型的毫秒時間
范例:使用Sleep方法暫緩線程
@Override
public?void?run() { ?//覆寫Runnable接口中的run方法
// TODO?Auto-generated method stub
//編寫線程的功能
for(int?i=0;i<30;i++) {
try?{
Thread.sleep(1000);
} catch?(InterruptedException e) {
// TODO?Auto-generated catch block
e.printStackTrace();
}
System.out.println(title+"="+i);
}
}
Runnable run=()->{
for(int?i=0;i<10;i++) {
try?{
Thread.sleep(1000);
} catch?(InterruptedException e) {
// TODO?Auto-generated catch block
e.printStackTrace();
}
System.out.println("線程"+i);}};
new?Thread(run).start();
3 線程的終斷
在Thread類中里面提供了線程的終斷的方法
?public?static?boolean?interrupted()
通過以上方法可以讓一個叫做正在休眠的線程終斷休眠
?public?static?boolean?interrupted()
以上方法可以判斷一個線程是否已經(jīng)被打斷,已經(jīng)被打斷線程不能再次被打斷
范例:線程的終斷
package?org.thread.demo;
public?class?ThreadDeme03 {
public?static?void?main(String[] args) {
Thread thread=new?Thread(()->{
System.out.println("薛哲同學(xué)憋了72個小時需要輸出");
try?{
Thread.sleep(100000); //輸出100秒
System.out.println("我只想安靜的蹲在這里抽一根煙");
} catch?(InterruptedException e) {
// TODO?Auto-generated catch block
System.out.println("誰也別來煩我");
e.printStackTrace();
}
});
thread.start(); //啟動線程 ?開始輸出
if(!thread.isInterrupted()) { //判斷是這個線程是否被打斷過 如果為true 沒有
System.out.println("李哲 嘿嘿一樂 想要偷偷去打斷一下");
thread.interrupt(); ?//打斷線程
}
}
}
4 線程的強(qiáng)制執(zhí)行
所謂線程的強(qiáng)制執(zhí)行九妈,指的是當(dāng)一個線程滿足條件之后反砌,會一直占用資源直到這個線程執(zhí)行完畢之后,其他線程在去訪問資源??
使用join關(guān)鍵則
public?final?void?join() throws?InterruptedException
5 線程的禮讓//就算你禮讓了 對面不走 還是自己走
public?static?native?void?yield();
所謂線程的禮讓就是在執(zhí)行的時候當(dāng)前不執(zhí)行允蚣,先讓別的線程執(zhí)行.在Thread中提供了一個
6線程的優(yōu)先級
線程的執(zhí)行的時候是可以設(shè)置優(yōu)先級的于颖,理論上來說誰的優(yōu)先級高誰就先執(zhí)行,但是在線程中優(yōu)先級也是一個叫做相對的概念嚷兔,而不是絕對的森渐。
1設(shè)置優(yōu)先級
?public?final?void?setPriority(int?newPriority)
public?final?int?getPriority() ;
通過以上代碼冒晰,可以對線程設(shè)置優(yōu)先級同衣,但是發(fā)現(xiàn)在設(shè)置優(yōu)先級之后線程的執(zhí)行也不是按照優(yōu)先級執(zhí)行的,優(yōu)先級只會對線程增加執(zhí)行的概率而已
范例:取得主線程的優(yōu)先級
System.out.println(Thread.currentThread().getPriority());
線程的同步與死鎖
在多線程中Thread描述的是一個個線程對象壶运,而Runnable描述的是資源耐齐,當(dāng)多個線程對象同時訪問同一資源,操作不當(dāng)?shù)那闆r下會產(chǎn)生數(shù)據(jù)的錯誤
同步問題的引出:
以上的問題為:多個對象同時訪問一個資源的時候,由于多個對象在搶占資源蒋情,有可能多個對象同一時間對資源進(jìn)行修改埠况,這樣就造成了數(shù)據(jù)的不同步
如果想要讓線程不出現(xiàn)數(shù)據(jù)錯誤的現(xiàn)象則需要在操作的資源上加上同步鎖,則這樣之后每一個線程對象在操作的資源的時候后面線程對象會等到之前的線程對象操作完畢之后才會進(jìn)行資源的操作
同步和異步:
異步:多個線程對象可以同一時間對資源進(jìn)行訪問
同步:同一時間只能有一個線程在操作資源棵癣,剩下的線程只能等待上一個線程操作完畢之后在進(jìn)行資源的操作
性能上的區(qū)別:
同步:由于每個線程只能單獨進(jìn)行資源的操作辕翰,所以效率不高
異步:異步處理由于多個線程可以同時進(jìn)行資源的訪問效率很高但是不安全
現(xiàn)在問題已經(jīng)分析出來了。主要的原因是異步和同步的問題狈谊,如果想要解決以上的問題則需要在操作資源上進(jìn)行同步鎖的添加
在多線程中可以用兩種方式實現(xiàn)同步鎖:
關(guān)鍵字:synchronized這個單詞必須能默寫出來
通過以上的關(guān)鍵字就可以實現(xiàn)兩種方式:
1同步代碼塊
synchronized?{}
2同步方法
public?synchronized?boolean?safe()
隊列又分為順序隊列和循環(huán)隊列
順序隊列存在假溢出的問題
由于順序隊列存在假溢出的問題喜命,所以可以使用循環(huán)隊列解決?特點:隊頭和隊尾首尾相連
在循環(huán)隊列中解決假溢出的問題:
判斷是否為空隊列
計數(shù)元素的個數(shù)
少使用一個空間
少使用一個空間的情況下:
(隊尾+1)%maxSize=front(隊頭)