Java線程類

基礎知識

線程狀態

根據Thread.State類中的描述,Java中線程有六種狀態:NEW,RUNNABLE,WAITING,TERMINATED,BLOCKED。ide

就緒狀態(NEW):當線程對象調用了start()方法以後,該線程就進入就緒狀態。就緒狀態的線程處於就緒隊列中,要等待JVM裏線程調度器的調度。this

運行狀態(RUNNABLE):若是就緒狀態的線程獲取 CPU 資源,就能夠執行 run(),此時線程便處於運行狀態。處於運行狀態的線程最爲複雜,它能夠變爲阻塞狀態、就緒狀態和死亡狀態。spa

阻塞狀態:若是一個線程執行了sleep(睡眠)、wait(等待)等方法,失去所佔用資源以後,該線程就從運行狀態進入阻塞狀態。在睡眠時間已到或得到設備資源後能夠從新進入就緒狀態。能夠分爲三種:操作系統

  • 等待阻塞(WAITING):運行狀態中的線程執行 wait() ,join(),park()方法,使線程進入到等待阻塞狀態。
  • 同步阻塞(BLOCKED):線程在獲取 synchronized 同步鎖失敗(由於同步鎖被其餘線程佔用)。
  • 其餘阻塞(TiMED_WAITHIN):經過調用線程的 sleep() 或 join() 發出了 I/O 請求時,線程就會進入到阻塞狀態。當sleep() 狀態超時,join() 等待線程終止或超時,或者 I/O 處理完畢,線程從新轉入運行態。

死亡狀態(TERMINATED):一個運行狀態的線程完成任務或者其餘終止條件發生時,該線程就切換到終止狀態。線程

值得注意的是,以上狀態爲JVM線程狀態,不反應操做系統線程狀態。code

                                            線程狀態遷移圖orm

線程優先級

每個 Java 線程都有一個優先級,這樣有助於操做系統肯定線程的調度順序。線程優先級是一個正整數,全部建立的線程默認優先級爲5(Thread.NORM_PRIORITY),可設置最大優先級爲10(Thread.MAX_PRIORITY),最小優先級爲1(Thread.MIN_PRIORITY)。在全部獲得其餘資源並等待處理器資源的線程中,優先級高的線程理論上將被更有可能被優先調度。對象

守護線程

守護線程意味着不重要的線程(騎士對於公主來講,是守護者,是無關緊要的備胎),於是當某進程只有守護線程在執行時,該進程會當即結束運行。    blog

建立可運行的類

繼承Thread類

1.新建類繼承Thread類。繼承

2.重寫run()方法。該run()方法的方法體就表明了線程須要完成的任務。 

3.建立Thread子類的實例。

4.調用線程對象的start()方法來啓動該線程。

public class myThread {
    public static void main(String[] args){
        Thread t = new newThread();
        t.start();
    }
}

class newThread extends Thread{
    @Override
    public void run() {
        System.out.println(this.getName()+":start!");
    }
}

實現Runnable接口

1.新建類實現Runnable接口。

2.重寫run方法。該run()方法的方法體就表明了線程須要完成的任務。

3.建立新建類的實例target。

4.以target做爲參數建立Thread的實例。

5.調用線程對象的start()方法來啓動該線程。

public class myThread {
    public static void main(String[] args){
        newThread nt = new newThread();
        Thread t = new Thread(nt);
        t.start();
    }
}

class newThread implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+":start!");
    }
}

兩種方法的優勢

1.繼承Thread這種方法方便易用,更容易獲取當前線程對象。

2.實現Runnable接口這種方法能夠繼承其餘父類;多個線程能夠共享一個target對象,適合多個相同線程來處理同一份資源的狀況。

能否直接調用run()方法開啓線程

事實上,線程對象只有調用start()方法才能在新的線程中運行run()方法體中的代碼,而直接調用run()方法意味着在當前線程中調用run()方法,即run()方法被看成普通方法處理了,並不會建立新線程

public class myThread {
    public static void main(String[] args){
        newThread nt = new newThread();
        Thread t = new Thread(nt,"myThread");
        t.run();
    }
}

class newThread implements Runnable{
    @Override
    public void run() {
        System.out.println("Name:"+Thread.currentThread().getName());
    }
}
//結果
Name:main

經常使用API

構造器

Thread() ,Thread(String name)   //能夠傳入一個字符串或什麼也不傳入,就是建立一個什麼任務也不作的線程

Thread(Runnable target)

Thread(Runnable target,String name)    //傳入一個可運行的對象,name做爲線程名稱

獲取線程信息

static Thread currentThread()      //獲取當前線程對象

long getID()            //獲取線程標識

String getName()     //獲取線程名稱

int getPriority()     //獲取線程優先級

Thread.state getState()     //獲取線程狀態

public class myThread {
    public static void main(String[] args){
        newThread nt = new newThread();
        Thread t = new Thread(nt,"myThread");
        t.start();
        newThread.getInformation(Thread.currentThread());
        newThread.getInformation(t);
    }
}

class newThread implements Runnable{
    @Override
    public void run() {
    }

    static void getInformation(Thread t){
        System.out.println("name:"+t.getName());
        System.out.println("id:"+t.getId());
        System.out.println("priority:"+t.getPriority());
        System.out.println("state:"+t.getState());
    }
}

//結果
name:main
id:1
priority:5
state:RUNNABLE
name:myThread
id:13
priority:5
state:TERMINATED

設置線程信息

void setName()    //設置線程名稱

void setPriority()    //設置線程優先級

void setDaemon(Boolean on)   //設置爲守護線程,只有當線程調用start()方法以前纔可調用

判斷線程狀態

boolean isAlive()        //判斷線程是否死亡,

boolean isDaemon()      //判斷線程是否爲守護線程

boolean isInterrupted()     //判斷線程是否中斷,而且將其變爲非中斷狀態

public class myThread {
    public static void main(String[] args){
        newThread nt = new newThread();
        Thread t = new Thread(nt,"myThread");
        System.out.println("未調用start()時:"+t.isAlive());
        t.setDaemon(true);
        t.start();
        newThread.getInformation(t);
        newThread.getInformation(Thread.currentThread());
    }
}

class newThread implements Runnable{
    @Override
    public void run() {
    }

    static void getInformation(Thread t){
        System.out.println(t.getName()+"-isAlive:"+t.isAlive());
        System.out.println(t.getName()+"-isDaemon:"+t.isDaemon());
        System.out.println(t.getName()+"-isInterrupted:"+t.isInterrupted());

    }
}

//結果
未調用start()時:false
myThread-isAlive:true
myThread-isDaemon:true
myThread-isInterrupted:false
main-isAlive:true
main-isDaemon:false
main-isInterrupted:false

sleep()方法

該方法讓當前線程暫停執行一段時間。

static void sleep(long millis)          //暫停millis毫秒

static void sleep(long millis,long nanos)    //暫停millis毫秒+nanos納秒

join()方法

join意味加入,能夠抽象地認爲它是加入當前線程隊伍,也就是說,發生t.join()調用時調用方t加入當前線程隊伍,當前線程須要等待t線程執行完畢後纔開始執行

public class myThread {
    public static void main(String[] args)throws InterruptedException {
        newThread nt = new newThread();
        Thread t = new Thread(nt,"subThread");
        t.start();
        t.join();
        for (int i = 1; i <= 1000; i++) {
            if (i%500==0) {
                System.out.println("mainThread finish!");
            }
        }

    }
}

class newThread implements Runnable{
    @Override
    public void run(){
        for (int i = 1; i <= 1000; i++) {
            try {
                Thread.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (i%500==0)
                System.out.println("subThread finish!");
        }
    }
}

結果以下,主線程顯然是比子線程執行時間更短,然而仍是主線程最後執行完

subThread finish!
subThread finish!
mainThread finish!
mainThread finish!

方法還有另外兩個重載形式

void join(long millis)          //等待millis毫秒

void join(long millis,long nanos)    //等待millis毫秒+nanos納秒

join()內部使用wait()方法和notifyall()方法來實現的,於是它與sleep()方法的區別是,sleep方法不會釋放持有的鎖,而join()方法會釋放持有的鎖。

//將t.join()改成t.join(50,50)後,結果不一樣:
mainThread finish!
mainThread finish!
subThread finish!
subThread finish!

yield()方法

讓出當前線程cup的使用權,此時就緒隊列中高優先級 的線程將被執行,此外該方法不釋放線程持有的鎖。

相關文章
相關標籤/搜索