1. 程式人生 > >java執行緒狀態詳解

java執行緒狀態詳解

執行緒狀態

執行緒狀態總共可分為五大狀態: 新建 可執行 執行 等待阻塞睡眠 死亡,如下圖所述:
在這裡插入圖片描述
1.新建(NEW): 執行緒物件已經建立,但還沒呼叫start()方法。
2.可執行(RUNNABLE): 當執行緒有資格執行,但還沒有獲得cpu資源。當start()方法呼叫後,執行緒先處於可執行狀態;當執行緒執行後或者從等待/阻塞/睡眠回來也可以進入可執行狀態。
3.執行(RUNNING): 當一個可執行狀態的執行緒獲得cpu資源後被執行的狀態。
4.阻塞(BLOCKED): 當一個處於執行態的執行緒出於某種原因暫時放棄了cpu的使用權從而進入阻塞態,直到執行緒進入可執行狀態才有機會在此獲得cpu使用權。
阻塞主要分為三種:

 4.1 等待阻塞:正在執行的執行緒執行wait()方法後,jvm會將該執行緒放入等待佇列(waiting queue)中.。
 4.2 同步阻塞:正在執行的執行緒獲取物件的同步鎖時,該同步鎖被其他執行緒佔用,則jvm會把該執行緒放入鎖池(lock pool)中。
 4.3 其他阻塞:當正在執行的執行緒執行Thread.sleep()、或者執行join()方法、或者發出了IO請求時,jvm會把該執行緒置為阻塞狀態,當sleep() 、join()終止時或者io請求結束後,該執行緒會再次進入可執行狀態。

5.死亡: 當執行緒的run()方法執行完,或者異常退出時run()方法時,該執行緒的生命週期結束,死亡的執行緒不可以復生。

可以阻止執行緒執行的方式

1.睡眠

Thread.sleep(long mills)和Thread.sleep(long mills,int nanos)兩個Thread類的靜態方法可以強制當前正在執行的執行緒進入睡眠狀態,甦醒之前不會進入可執行狀態,當睡眠時間結束後再次進入可執行時間。
執行緒睡眠原因: 執行緒執行太快或者需要強制進入下一輪。
睡眠實現: 呼叫靜態方法Thread.sleep()
睡眠的位置: 為了讓其他執行緒有機會執行,可以將Thread.sleep()放在需要睡眠的執行緒的run方法裡面;

/**
 * @author FengTianHao
 * @version 1.0
 * @since 2018/11/15 17:04
 */






public class TestThread implements Runnable {
    private String name;
    public TestThread(String name) {
        this.name = name;
    }
    @Override
    public void run()
    {
        for(int i=0;i<100;i++)
        {
            System.out.println(name+i);
            try {
                Thread.sleep(30);//每到執行緒執行到這時會休眠30毫秒,給其他執行緒提供執行的機會
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args)
    {
        TestThread zhangsan=new TestThread("張三");
        Thread t1=new Thread(zhangsan);
        t1.start();
        TestThread lisi=new TestThread("李四");
        Thread t2=new Thread(lisi);
        t2.start();
    }

}

執行結果:
在這裡插入圖片描述
這樣執行緒每次執行的過程中都會休眠30毫秒,其他的執行緒就有機會執行啦。關於執行緒建立的方式有不懂地方可以看看博主的建立執行緒的主要三種方式
注意:

(1). 執行緒睡眠是所有執行緒獲得執行機會的最好方法。
(2). 當睡眠時間結束後執行緒進入可執行狀態而不是執行狀態,即sleep()方法不能保證執行緒睡眠結束後立即進入執行狀態。
(3). sleep()是Thred類的靜態方法,它只能控制當前正在執行的執行緒

2.執行緒的優先順序和執行緒讓步yield()

執行緒的讓步是通過Thread.yield()來實現的,yield()方法的作用:暫停當前正在執行的執行緒並執行其他的執行緒,被暫停的執行緒進入可執行狀態。要理解yield()方法必須得先了解執行緒優先順序的概念。執行緒存在優先順序,範圍:1~10;jvm排程執行緒總是基於優先順序搶先排程機制。在大多數情況下,正在執行的執行緒優先順序高於或者等於執行緒池的其他執行緒。但也是僅僅是大多數情況。
設定執行緒的優先順序
執行緒建立好後會有一個預設優先順序,可以通過setPriority(int newPriority)方法來設定新的優先順序。優先順序的高低代表著獲得cpu的概率的高低,但是在現實中並沒有多少用。
例如:

		TestThread zhangsan=new TestThread("張三");
        Thread t1=new Thread(zhangsan);
        t1.setPriority(10);

執行緒預設的優先順序是5,Thread類中有三個常量來表示優先順序的範圍
static int MAX_PRIORITY 10; 執行緒可以擁有的最高優先順序
static int MIN_PRIORITY 1; 執行緒可以擁有的最低優先順序
static int NORM_PRIORITY 5;執行緒的預設優先順序
Thread.yield()方法
作用: 暫停正在執行的執行緒,執行其他的執行緒
呼叫yield()方法後,使得當前執行的執行緒進入可執行狀態,然後允許優先權相等的其他執行緒獲得執行的機會,因此,使用yield()方法可以使得有相同優先權的執行緒可以輪轉執行;但現實中yield()方法並不可以保證執行緒讓步,呼叫yield()方法的執行緒在下一輪可能又會被排程。
join()方法
join()方法是Thread類的一個非靜態方法,它使一個執行緒a追加到一個執行緒b的尾部,線上程b執行完之前不可以執行。
例如:

    	 TestThread zhangsan=new TestThread("張三");
         Thread b=new Thread(zhangsan);
         b.start();
         TestThread lisi=new TestThread("李四");
         Thread a=new Thread(lisi);
        a.start();
        如果沒用用join(),這樣的話執行緒a和執行緒b為併發執行
 		TestThread zhangsan=new TestThread("張三");
         Thread b=new Thread(zhangsan);
         b.start();
         b.join();
         TestThread lisi=new TestThread("李四");
         Thread a=new Thread(lisi);
        a.start();
        使用join()後,這樣的話執行緒a和執行緒b為同步執行,b先執行完後a開始執行

join()方法還可以使執行緒進入等待狀態,例:

a.join(5000);
a執行緒進入等待狀態並持續5000毫秒,等待結束後進入可執行狀態

小結
使執行緒離開執行狀態的方式有三種

  1. 呼叫Thread.sleep()可以使當前執行的執行緒睡眠多少毫秒。
  2. 呼叫Thread.yeild()使當前執行的執行緒回到可執行狀態,除此之外不能保證什麼。
  3. 呼叫join()方法可以當前執行緒停止執行直到加入的執行緒執行完為止。