java線程的基礎(chǔ)實(shí)例解析
java中建立線程可以有兩種方式,分別是繼承Thread類和實(shí)現(xiàn)Runnable接口。
繼承Thread
public class MyThread extends Thread{
public MyThread(String name){
super(name);
}
int i;
public void run(){
for(i=0;i<5;i++){
System.out.println(getName()+"--"+i);
}
}
public static void main(String[] agrs){
new MyThread("線程1").start();
new MyThread("線程2").start();
}
}
/*
線程1--0
線程1--1
線程1--2
線程1--3
線程1--4
線程2--0
線程2--1
線程2--2
線程2--3
線程2--4
*/
如上,java中的線程對(duì)象必須一個(gè)類的形式創(chuàng)建,而該類中必須重寫基類的run()方法,該方法其實(shí)就是線程的執(zhí)行體。調(diào)用該類實(shí)例的start方法則就隱式的調(diào)用了run方法。
不難看出,由于new了2次MyThread,所以兩次的實(shí)例是不同的,即各自都有各自的i變量,相互獨(dú)立。
Runnable接口
public class MyRunnable implements Runnable{
int i;
public void run(){
for(i=0;i<50;i++){
System.out.println(Thread.currentThread().getName()+"--"+i);//不能直接this.getName()
}
}
public static void main(String[] agrs){
MyRunnable myRun=new MyRunnable();
new Thread(myRun,"線程1").start();
new Thread(myRun,"線程2").start();
}
}
/*
線程1--0
線程1--1
線程2--0
線程2--3
線程2--4
線程2--5
線程2--6
線程2--7
線程2--8
線程2--9
線程2--10
線程2--11
線程2--12
線程2--13
線程2--14
線程2--15
線程1--2
線程2--16
線程2--18
線程2--19
線程2--20
線程2--21
線程2--22
線程2--23
線程2--24
線程1--17
線程2--25
線程1--26
線程2--27
線程1--28
線程1--30
線程2--29
線程1--31
線程2--32
線程2--34
線程2--35
線程2--36
線程2--37
線程1--33
線程2--38
線程1--39
線程1--41
線程2--40
線程1--42
線程1--44
線程1--45
線程2--43
線程1--46
線程2--47
線程2--49
線程1--48
*/
可以看出,由于實(shí)現(xiàn)這種方式是將某一個(gè)對(duì)象做為target加載到Thread類上,所以即使new再多的Thread對(duì)象,只要target是同一引用的對(duì)象,則就調(diào)用該對(duì)象的run方法,所有線程均共享該target對(duì)象的資源,所以會(huì)看到線程1和線程2一共輸出了51次,2條線程共同完成了i從0到49的輸出,而并不像上面那樣分別輸出5次。至于為什么輸出了51條,兩條線程幾乎在同一時(shí)刻進(jìn)入就緒狀態(tài)(start方法只是讓線程進(jìn)入就緒狀態(tài)),觀察上面的i變量不難發(fā)現(xiàn)當(dāng)i等于0時(shí),此時(shí)線程1和線程2均同時(shí)處于運(yùn)行狀態(tài),產(chǎn)生了并發(fā)現(xiàn)象,共同輸出了i=0,而此之后CPU通過(guò)不斷的切換線程,使得在同一時(shí)刻只有一條線程在輸出。
線程狀態(tài)
線程分為4個(gè)狀態(tài)
就緒狀態(tài):調(diào)用start方法則進(jìn)入就緒狀態(tài)。
運(yùn)行狀態(tài):處于就緒狀態(tài)的線程會(huì)被jvm進(jìn)行調(diào)度從而成為運(yùn)行狀態(tài)。
阻塞狀態(tài):如有某些同步方法未返回結(jié)果則出現(xiàn)阻塞狀態(tài),或sleep和yeild。
死亡狀態(tài):方法體執(zhí)行完畢或者強(qiáng)行stop某個(gè)線程。
線程的基本操作
join()合并線程:當(dāng)前線程調(diào)用某線程的join方法后將會(huì)等待某線程執(zhí)行完畢后本線程才會(huì)繼續(xù)。
sleep(long milliseconds)線程睡眠:阻塞當(dāng)前線程,只有阻塞的時(shí)間到了才會(huì)繼續(xù)下去。再阻塞的同時(shí),會(huì)將CPU占有權(quán)交給其他線程,所以常常利用sleep(1)來(lái)切換線程。
**yield()線程讓步:**yeild類似與sleep,但是它只會(huì)讓步于比自己級(jí)別高或者同級(jí)別的其他線程,若沒(méi)有其他線程均比自己級(jí)別低則再次執(zhí)行本線程。
后臺(tái)線程
一個(gè)程序被操作系統(tǒng)執(zhí)行后將有一個(gè)進(jìn)程,一個(gè)進(jìn)程至少有一個(gè)線程(主線程),主線程并沒(méi)有比其他線程有太多的特殊之處,只因?yàn)樗亲钤绫粓?zhí)行的線程,在主線程中將會(huì)創(chuàng)建其他線程,若不指明則默認(rèn)創(chuàng)建的是前臺(tái)線程(包括main線程),若調(diào)用setDaemon(true)則顯式的將該線程設(shè)置為后臺(tái)線程,后臺(tái)線程為Daemon線程,從名字就能看出,它的主要作用是為其他線程提供守護(hù),服務(wù)的功能。當(dāng)所有前臺(tái)線程結(jié)束后,后臺(tái)線程將會(huì)被強(qiáng)制結(jié)束,因?yàn)樗藭r(shí)已經(jīng)沒(méi)有存在的意義了。
前臺(tái)線程
public class ForeAndBackThread extends Thread{
public ForeAndBackThread(String name){
super(name);
}
public void run(){
int i;
for(i=0;i<9999;i++){
System.out.println(this.getName()+"--"+i);
}
}
public static void main(String[] args){
ForeAndBackThread th=new ForeAndBackThread("線程A");
//th.setDaemon(true);
th.start();
int j;
for(j=0;j<3;j++){
System.out.println(Thread.currentThread().getName()+"--"+j);
}
}
}
程序完整的輸出子線程中0到9998;說(shuō)明主線程并沒(méi)有什么特殊的,它的結(jié)束并不會(huì)影響其他前臺(tái)線程的運(yùn)行。
后臺(tái)線程
public class ForeAndBackThread extends Thread{
public ForeAndBackThread(String name){
super(name);
}
public void run(){
int i;
for(i=0;i<9999;i++){
System.out.println(this.getName()+"--"+i);
}
}
public static void main(String[] args){
ForeAndBackThread th=new ForeAndBackThread("線程A");
th.setDaemon(true);
th.start();
int j;
for(j=0;j<3;j++){
System.out.println(Thread.currentThread().getName()+"--"+j);
}
}
}
程序并不能完整的輸出0-9998就退出了,說(shuō)明前臺(tái)主線程結(jié)束后,jvm強(qiáng)制結(jié)束了后臺(tái)線程。
總結(jié)
以上就是本文關(guān)于java線程的基礎(chǔ)實(shí)例解析的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對(duì)本站的支持!
相關(guān)文章
詳解jdbc實(shí)現(xiàn)對(duì)CLOB和BLOB數(shù)據(jù)類型的操作
這篇文章主要介紹了詳解jdbc實(shí)現(xiàn)對(duì)CLOB和BLOB數(shù)據(jù)類型的操作的相關(guān)資料,這里實(shí)現(xiàn)寫入操作與讀寫操作,需要的朋友可以參考下2017-08-08
Maven倉(cāng)庫(kù)的具體使用(本地倉(cāng)庫(kù)+遠(yuǎn)程倉(cāng)庫(kù))
Maven 在某個(gè)統(tǒng)一的位置存儲(chǔ)所有項(xiàng)目的構(gòu)件,這個(gè)統(tǒng)一的位置,我們就稱之為倉(cāng)庫(kù),本文主要介紹了Maven倉(cāng)庫(kù)的具體使用(本地倉(cāng)庫(kù)+遠(yuǎn)程倉(cāng)庫(kù)),感興趣的可以了解一下2023-11-11
java存儲(chǔ)以及java對(duì)象創(chuàng)建的流程(詳解)
下面小編就為大家?guī)?lái)一篇java存儲(chǔ)以及java對(duì)象創(chuàng)建的流程(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-05-05
深入理解MyBatis中的一級(jí)緩存與二級(jí)緩存
這篇文章主要給大家深入的介紹了關(guān)于MyBatis中一級(jí)緩存與二級(jí)緩存的相關(guān)資料,文中詳細(xì)介紹MyBatis中一級(jí)緩存與二級(jí)緩存的工作原理及使用,對(duì)大家具有一定的參考性學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-06-06
SpringBoot統(tǒng)計(jì)接口調(diào)用耗時(shí)的三種方式
在實(shí)際開(kāi)發(fā)中,了解項(xiàng)目中接口的響應(yīng)時(shí)間是必不可少的事情,SpringBoot 項(xiàng)目支持監(jiān)聽(tīng)接口的功能也不止一個(gè),接下來(lái)我們分別以 AOP、ApplicationListener、Tomcat 三個(gè)方面去實(shí)現(xiàn)三種不同的監(jiān)聽(tīng)接口響應(yīng)時(shí)間的操作,需要的朋友可以參考下2024-06-06
面向?qū)ο缶幊?Java中的抽象數(shù)據(jù)類型
面向?qū)ο缶幊?Java中的抽象數(shù)據(jù)類型...2006-12-12
Java并發(fā)編程之ReentrantLock實(shí)現(xiàn)原理及源碼剖析
ReentrantLock 是常用的鎖,相對(duì)于Synchronized ,lock鎖更人性化,閱讀性更強(qiáng),文中將會(huì)詳細(xì)的說(shuō)明,請(qǐng)君往下閱讀2021-09-09
Mybatis的xml中使用if/else標(biāo)簽的具體使用
本文主要介紹了Mybatis的xml中使用if/else標(biāo)簽的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05

