初步學(xué)習(xí)Java中線程的實現(xiàn)與生命周期
線程的實現(xiàn)
在Java中通過run方法為線程指明要完成的任務(wù),有兩種技術(shù)來為線程提供run方法:
1.繼承Thread類并重寫它的run方法。之后創(chuàng)建這個子類的對象并調(diào)用start()方法。
2.通過定義實現(xiàn)Runnable接口的類進(jìn)而實現(xiàn)run方法。這個類的對象在創(chuàng)建Thread的時候作為參數(shù)被傳入,然后調(diào)用start()方法。
Thread類是專門用來創(chuàng)建線程和對線程進(jìn)行操作的類。當(dāng)某個類繼承了Thread類之后,該類就叫做一個線程類。
兩種方法均需執(zhí)行線程的start()方法為線程分配必須的系統(tǒng)資源、調(diào)度線程運(yùn)行并執(zhí)行線程的run()方法。
start()方法是啟動線程的唯一的方法。start()方法首先為線程的執(zhí)行準(zhǔn)備好系統(tǒng)資源,然后再去調(diào)用run()方法。一個線程只能啟動一次,再次啟動就不合法了。
run()方法中放入了線程的工作,即我們要這個線程去做的所有事情。缺省狀況下run()方法什么也不做。
在具體應(yīng)用中,采用哪種方法來構(gòu)造線程要視情況而定。通常,當(dāng)一個線程已經(jīng)繼承了另一個類時,就應(yīng)該用第二種方法來構(gòu)造,即實現(xiàn)Runnable接口。
下面給出兩個例子來說明線程的兩種實現(xiàn)方法,每個例子中都有兩個線程:\
public class ThreadTest1
{
public static void main(String[] args)
{
Thread1 thread1 = new Thread1();
Thread2 thread2 = new Thread2();
thread1.start();
thread2.start();
}
}
class Thread1 extends Thread
{
@Override
public void run()
{
for (int i = 0; i < 100; ++i)
{
System.out.println("Hello World: " + i);
}
}
}
class Thread2 extends Thread
{
@Override
public void run()
{
for (int i = 0; i < 100; ++i)
{
System.out.println("Welcome: " + i);
}
}
}
public class ThreadTest2
{
public static void main(String[] args)
{
// 線程的另一種實現(xiàn)方法,也可以使用匿名的內(nèi)部類
Thread thread1 = new Thread(new MyThread1());
thread1.start();
Thread thread2 = new Thread(new MyThread2());
thread2.start();
}
}
class MyThread1 implements Runnable
{
@Override
public void run()
{
for (int i = 0; i < 100; ++i)
{
System.out.println("Hello: " + i);
}
}
}
class MyThread2 implements Runnable
{
@Override
public void run()
{
for (int i = 0; i < 100; ++i)
{
System.out.println("Welcome: " + i);
}
}
}
Thread類剖析
Thread類也實現(xiàn)了Runnable接口,因此實現(xiàn)了接口中的run()方法。
當(dāng)生成一個線程對象時,如果沒有為其指定名字,那么線程對象的名字將使用如下形式:Thread-number,該number是自動增加的數(shù)字,并被所有的Thread對象所共享,因為它是一個static的成員變量。
當(dāng)使用第一種方式(繼承Thread的方式)來生成線程對象時,我們需要重寫run()方法,因為Thread類的run()方法此時什么事情也不做。
當(dāng)使用第二種方式(實現(xiàn)Runnable接口的方式)來生成線程對象時,我們需要實現(xiàn)Runnable接口的run()方法,然后使用new Thread(new MyRunnableClass())來生成線程對象(MyRunnableClass已經(jīng)實現(xiàn)了Runnable接口),這時的線程對象的run()方法會調(diào)用MyRunnableClass的run()方法。
停止線程
線程的消亡不能通過調(diào)用stop()命令,而是讓run()方法自然結(jié)束。stop()方法是不安全的,已經(jīng)廢棄。
停止線程推薦的方式:設(shè)定一個標(biāo)志變量,在run()方法中是一個循環(huán),由該標(biāo)志變量控制循環(huán)是繼續(xù)執(zhí)行還是跳出;循環(huán)跳出,則線程結(jié)束。
如代碼例子中所示:
public class ControlThreadTest
{
MyThreadClass r = new MyThreadClass();
Thread t = new Thread(r);
public void startThread()
{
t.start();
}
public void stopThread()
{
r.stopRunning();
}
}
class MyThreadClass implements Runnable
{
private boolean flag = true;
@Override
public void run()
{
while (flag)
{
System.out.println("Do something.");
}
}
public void stopRunning()
{
flag = false;
}
}
線程的生命周期及優(yōu)先級
線程的生命周期
線程的生命周期:一個線程從創(chuàng)建到消亡的過程。
如下圖,表示線程生命周期中的各個狀態(tài):

線程的生命周期可以分為四個狀態(tài):
1.創(chuàng)建狀態(tài):
當(dāng)用new操作符創(chuàng)建一個新的線程對象時,該線程處于創(chuàng)建狀態(tài)。
處于創(chuàng)建狀態(tài)的線程只是一個空的線程對象,系統(tǒng)不為它分配資源。
2.可運(yùn)行狀態(tài):
執(zhí)行線程的start()方法將為線程分配必須的系統(tǒng)資源,安排其運(yùn)行,并調(diào)用線程體——run()方法,這樣就使得該線程處于可運(yùn)行狀態(tài)(Runnable)。
這一狀態(tài)并不是運(yùn)行中狀態(tài)(Running),因為線程也許實際上并未真正運(yùn)行。
3.不可運(yùn)行狀態(tài):
當(dāng)發(fā)生下列事件時,處于運(yùn)行狀態(tài)的線程會轉(zhuǎn)入到不可運(yùn)行狀態(tài):
調(diào)用了sleep()方法;
線程調(diào)用wait()方法等待特定條件的滿足;
線程輸入/輸出阻塞。
返回可運(yùn)行狀態(tài):
處于睡眠狀態(tài)的線程在指定的時間過去后;
如果線程在等待某一條件,另一個對象必須通過notify()或notifyAll()方法通知等待線程條件的改變;
如果線程是因為輸入輸出阻塞,等待輸入輸出完成。
4.消亡狀態(tài):
當(dāng)線程的run()方法執(zhí)行結(jié)束后,該線程自然消亡。
線程的優(yōu)先級
1.線程的優(yōu)先級及設(shè)置
線程的優(yōu)先級是為了在多線程環(huán)境中便于系統(tǒng)對線程的調(diào)度,優(yōu)先級高的線程將優(yōu)先執(zhí)行。
一個線程的優(yōu)先級設(shè)置遵從以下原則:
線程創(chuàng)建時,子繼承父的優(yōu)先級。
線程創(chuàng)建后,可通過調(diào)用setPriority()方法改變優(yōu)先級。
線程的優(yōu)先級是1-10之間的正整數(shù)。
1- MIN_PRIORITY
10-MAX_PRIORITY
5-NORM_PRIORITY
如果什么都沒有設(shè)置,默認(rèn)值是5。
但是不能依靠線程的優(yōu)先級來決定線程的執(zhí)行順序。
2.線程的調(diào)度策略
線程調(diào)度器選擇優(yōu)先級最高的線程運(yùn)行。但是,如果發(fā)生以下情況,就會終止線程的運(yùn)行:
線程體中調(diào)用了yield()方法,讓出了對CPU的占用權(quán)。
線程體中調(diào)用了sleep()方法,使線程進(jìn)入睡眠狀態(tài)。
線程由于I/O操作而受阻塞。
另一個更高優(yōu)先級的線程出現(xiàn)。
在支持時間片的系統(tǒng)中,該線程的時間片用完。
相關(guān)文章
Spring MVC之mvc:resources如何處理靜態(tài)資源
這篇文章主要介紹了Spring MVC之mvc:resources如何處理靜態(tài)資源問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-03-03
java實現(xiàn)兩張圖片2D翻轉(zhuǎn)動畫效果
這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)兩張圖片2D翻轉(zhuǎn)動畫效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-08-08
JAVA Stack詳細(xì)介紹和示例學(xué)習(xí)
JAVA Stack是棧。它的特性是:先進(jìn)后出(FILO, First In Last Out)。2013-11-11
java 定時器Timer和TimerTask的使用詳解(執(zhí)行和暫停)
這篇文章主要介紹了java 定時器Timer和TimerTask的使用詳解(執(zhí)行和暫停),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2023-11-11
Java超詳細(xì)講解WebMvcConfigurer攔截器
這篇文章將用實例來和大家介紹一下WebMvcConfigurer攔截器。文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Java有一定的幫助,需要的可以參考一下2022-06-06
SpringCloud實現(xiàn)灰度發(fā)布的方法步驟
本文主要介紹了SpringCloud實現(xiàn)灰度發(fā)布的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05
TOMCAT內(nèi)存溢出及大小調(diào)整的實現(xiàn)方法
下面小編就為大家?guī)硪黄猅OMCAT內(nèi)存溢出及大小調(diào)整的實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-05-05

