java 线程 状态 图_Java提高——多线程(一)状态图
操作系統(tǒng)中的進(jìn)程和線程的概念
進(jìn)程是指一個(gè)內(nèi)存運(yùn)行的應(yīng)用程序,每個(gè)進(jìn)程都有自己獨(dú)立的一塊內(nèi)存空間,一個(gè)進(jìn)程中可以啟動(dòng)多個(gè)線程,比如windows下的一個(gè)運(yùn)行的應(yīng)用程序.exe就是一個(gè)進(jìn)程。
線程是指進(jìn)程中的一個(gè)執(zhí)行流,一個(gè)進(jìn)程可以運(yùn)行多個(gè)線程。如java.exe就可以運(yùn)行很多個(gè)線程。線程總是屬于某個(gè)進(jìn)程,進(jìn)程中的多個(gè)線程共享進(jìn)程中的內(nèi)存。
操作系統(tǒng)中可以同時(shí)執(zhí)行多個(gè)任務(wù),每個(gè)任務(wù)就是進(jìn)程;進(jìn)程可以同時(shí)執(zhí)行多個(gè)任務(wù),每個(gè)任務(wù)就是線程。
線程的狀態(tài)
1、新建(new):線程對(duì)象被創(chuàng)建后就進(jìn)入了新建狀態(tài)。如:Thread thread = new Thread();
2、就緒狀態(tài)(Runnable):也被稱為“可執(zhí)行狀態(tài)”。線程對(duì)象被創(chuàng)建后,其他線程調(diào)用了該對(duì)象的start()方法,從而啟動(dòng)該線程。如:thread.start(); 處于就緒狀態(tài)的線程隨時(shí)可能被CPU調(diào)度執(zhí)行。
3、運(yùn)行狀態(tài)(Running):線程獲取CPU權(quán)限進(jìn)行執(zhí)行。需要注意的是,線程只能從就緒狀態(tài)進(jìn)入到運(yùn)行狀態(tài)。
4、阻塞狀態(tài)(Blocked):阻塞狀態(tài)是線程因?yàn)槟撤N原因放棄CPU使用權(quán)限,暫時(shí)停止運(yùn)行。直到線程進(jìn)入就緒狀態(tài),才有機(jī)會(huì)進(jìn)入運(yùn)行狀態(tài)。阻塞的三種情況:
1)等待阻塞:通過調(diào)用線程的wait()方法,讓線程等待某工作的完成。
2)同步阻塞:線程在獲取synchronized同步鎖失敗(因?yàn)殒i被其他線程占用),它會(huì)進(jìn)入同步阻塞狀態(tài)。
3)其他阻塞:通過調(diào)用線程的sleep()或join()或發(fā)出了I/O請(qǐng)求時(shí),線程會(huì)進(jìn)入到阻塞狀態(tài)。當(dāng)sleep()狀態(tài)超時(shí)、join()等待線程終止或超時(shí)、或者I/O處理完畢時(shí),線程重新轉(zhuǎn)入就緒狀態(tài)。
5、死亡狀態(tài)(Dead):線程執(zhí)行完了或因異常退出了run()方法,該線程結(jié)束生命周期。
常用的實(shí)現(xiàn)多線程的方式
1、繼承Thread類publicclassThread implementsRunnable {、、、、、}
由Thread的源碼可以看出,Thread是實(shí)現(xiàn)了Runnable接口。
2、實(shí)現(xiàn)Runnable接口
publicinterfaceRunnable {
public abstract voidrun();}
Runnable接口只有一個(gè)run()方法
————————————————————————————————————————————————
Thread和Runnable都是是實(shí)現(xiàn)實(shí)現(xiàn)多線程的方式。不同的是Thread是類,Runnable是接口——Thread本身實(shí)現(xiàn)了Runnable接口,一個(gè)類只能有一個(gè)父類,但是卻可以是實(shí)現(xiàn)多個(gè)接口,因此Runnable具有更好的擴(kuò)展性。
Thread實(shí)現(xiàn)多線程public classMyThread extendsThread {
private inti;@Override/** 重寫run方法*/public voidrun(){
for(inti = 0;i < 50;i++) {
/*** 當(dāng)繼承Thread類可以直接用this獲取當(dāng)前線程* 用getName()獲取當(dāng)前線程的名字*/System.out.println(this.getName()+"-"+i);}
}
public static voidmain(String[] args) {
for(inti = 0;i < 100;i++) {
//通過Thread.currentThread()獲取當(dāng)前線程System.out.println(Thread.currentThread().getName()+" "+i);if(i==20){
//創(chuàng)建并啟動(dòng)第一個(gè)線程newMyThread().start();//創(chuàng)建并啟動(dòng)第二個(gè)線程newMyThread().start();}
}
}
}
Runnable實(shí)現(xiàn)多線程public classMyRunnable implementsRunnable {
private inti;@Overridepublic voidrun() {
for(inti = 0;i < 50;i++) {
/**當(dāng)線程類實(shí)現(xiàn)Runnable接口的時(shí)候,獲取當(dāng)前線程只能用Thread.currentThread()*/System.out.println(Thread.currentThread().getName()+" "+i);}
}
public static voidmain(String[] args) {
for(inti = 0;i < 100;i++) {
// System.out.println(Thread.currentThread().getName()+" "+i);if(i==20){
MyRunnable mr = newMyRunnable();//通過new Start()方法創(chuàng)建新線程newThread(mr,"線程1").start();newThread(mr,"線程2").start();}
}
}
}
關(guān)于線程中的start()和run()
啟動(dòng)線程使用start(),而不是run()!
在執(zhí)行start()方法之前,只是有一個(gè)Thread對(duì)象,還沒一個(gè)真正的線程。(分配內(nèi)存,初始化成員變量)
——>start()之后,線程狀態(tài)從新狀態(tài)到可執(zhí)行狀態(tài)。(調(diào)用棧和計(jì)數(shù)器,線程沒運(yùn)行,只是可以運(yùn)行)
——>當(dāng)線程獲得執(zhí)行機(jī)會(huì)時(shí),其目標(biāo)run()方法將運(yùn)行。
start():他的作用是啟動(dòng)一個(gè)新線程,新線程會(huì)調(diào)用相應(yīng)的run()方法。start()不能被重復(fù)調(diào)用。
run():和普通成員的方法一樣可以被重復(fù)調(diào)用。單獨(dú)調(diào)用run()會(huì)在當(dāng)前線程中執(zhí)行run(),而不會(huì)啟動(dòng)新的線程。
public classMyThread extendsThread {@Override/** 重寫run方法*/public voidrun(){
}
}
MyThread myThread = new MyThread();
如:myThread.start()會(huì)啟動(dòng)一個(gè)新的線程,然后在新線程中執(zhí)行run()方法。
myThread.run()會(huì)直接在當(dāng)前線程中運(yùn)行run()方法,不會(huì)啟動(dòng)一個(gè)線程。
start方法源碼:public synchronized voidstart() {
/**
*如果線程不是就緒狀態(tài)就拋出異常*/if(threadStatus!= 0)
throw newIllegalThreadStateException();/* 將線程添加到group當(dāng)中 */group.add(this);booleanstarted = false;try{
start0();//通過start0啟動(dòng)線程started = true;//設(shè)置started標(biāo)記} finally{
try{
if(!started) {
group.threadStartFailed(this);}
} catch(Throwable ignore) {
/* do nothing. If start0 threw a Throwable thenit will be passed up the call stack */}
}
}
run方法源碼:public voidrun() {
if(target!= null) {
target.run();}
}
其中target是Runnable對(duì)象, 直接調(diào)用Thread線程中Runnable接口中run方法,不會(huì)新建一個(gè)線程。
當(dāng)線程獲得CPU,開始執(zhí)行run()方法的線程執(zhí)行體,則該線程處于運(yùn)行狀態(tài)。
關(guān)于阻塞
進(jìn)入阻塞的情況:解除上面阻塞情況:
1、線程調(diào)用sleep()方法主動(dòng)釋放占用的處理器資源
2、調(diào)用了一個(gè)阻塞式的IO方法,在方法返回前線程被阻塞
3、線程獲得了一個(gè)同步監(jiān)視器(Syschronized),但該監(jiān)視器正被其他線程持有
4、線程在等待某個(gè)通知(notify)
5、程序調(diào)用了線程的resume()方法將線程掛起。但是該方法容易發(fā)生死鎖,所以盡量避免使用1、調(diào)用sleep()方法經(jīng)過了指定的時(shí)間
2、線程調(diào)用的IO阻塞方法已經(jīng)返回
3、線程成功的獲得了試圖取得的同步監(jiān)視器
4、線程正在等待某個(gè)通知時(shí),其他線程發(fā)出了一個(gè)通知
5、處于掛起的線程被調(diào)用了resume()恢復(fù)方法。
線程從阻塞狀態(tài)只能進(jìn)入就緒狀態(tài),無法進(jìn)入運(yùn)行狀態(tài),而從就緒到運(yùn)行不受程序控制,由系統(tǒng)線程調(diào)度決定。
獲得資源進(jìn)入運(yùn)行狀態(tài),失去資源進(jìn)入就緒狀態(tài)。
線程死亡
線程死亡會(huì)以一下三種狀況結(jié)束:
—>調(diào)用run或call方法執(zhí)行完成,正常結(jié)束
—>線程拋出一個(gè)為捕獲的Exception或Error
—>直接調(diào)用stop()方法來結(jié)束該線程——容易導(dǎo)致死鎖,不推薦。
不要試圖對(duì)死亡的線程使用start()方法,將會(huì)拋出異常,并不會(huì)重啟死亡的異常!
總結(jié)
以上是生活随笔為你收集整理的java 线程 状态 图_Java提高——多线程(一)状态图的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 阿里云oss 简单上传
- 下一篇: Java 数据库基本操作