1. 程式人生 > 其它 >java基礎知識回顧之java Thread類學習(四)--執行緒的狀態以及轉化使用的方法介紹

java基礎知識回顧之java Thread類學習(四)--執行緒的狀態以及轉化使用的方法介紹

java基礎知識回顧之java Thread類學習(十)--執行緒的狀態以及轉化使用的方法介紹

執行緒的概述:

執行緒是程式的多個執行路徑,執行排程的單位,依託於程序存在。執行緒不僅可以共享程序的記憶體,而且還擁有一個屬於自己的記憶體空間,這段記憶體空間叫做執行緒棧,是建立執行緒的時候由系統分配的,主要用來儲存執行緒內部的資料,如執行緒執行函式中定義的變數。

  java中多執行緒是一種搶佔機制而不是分時機制。搶佔機制是指CPU資源師被多個執行緒所共享,多個執行緒處於可執行狀態,但是隻允許一個執行緒在執行,他們通過競爭的方式搶佔CPU.可以參考java 程序與執行緒的區別

執行緒的狀態:

  • 新生狀態(New):當一個執行緒被建立一個執行緒例項後new Thread()或者new Thread(Runnable r),此執行緒處於新生狀態,處於新生狀態,執行緒有自己的記憶體空間,但該執行緒沒有執行,此時該執行緒還不是活著的(not Alive)。
  • 就緒狀態(Runnable):通過執行緒物件的start()方法啟動執行緒使執行緒進入就緒狀態(runnable),處於就緒狀態的執行緒具備了執行條件(CPU執行資格),但是還沒有搶到CPU執行權,不一定會被立即執行。此時執行緒線上程就緒佇列中,等待系統為其分配CPU.等待狀態不是執行狀態,此時執行緒是活著的(isAlive=true).
  • 執行狀態(Running):一旦執行緒搶到CPU執行權,執行緒進入執行狀態(running),執行緒run方法才開始執行,執行狀態的執行緒執行自己run方法裡面的程式碼,直到呼叫其他方法而終止,或者等待某種資源而阻塞,或者完成任務而死亡;如果再給定的時間片內程式沒有執行結束,就會被系統暫停當前正在執行的排程程式,回到執行緒的等待狀態。此時執行緒是活著的(Alive)
  • 阻塞狀態:(Blocked):通過呼叫join,sleep,wait或者資源被佔用,使執行緒處於阻塞狀態(blocked),處於阻塞狀態的執行緒仍然活著。
  • 死亡狀態:(Dead):當一個執行緒的run方法中的程式碼執行完畢,或被中斷,或被異常退出,該執行緒處於死亡狀態。一旦執行緒進入dead狀態,它就再也不能進入一個獨立執行緒的生命週期了,對一個處於dead狀態的執行緒呼叫start方法,會出現runtime exception異常;處於dead狀態的執行緒不是活著的(Alive)

執行緒的方法和屬性:

  • 優先順序(priority):每一個執行緒都有一個優先順序。預設優先順序是5,優先順序最高是10;優先順序高的執行緒並不一定比優先順序低的執行緒執行的機會高,只是執行的機率高;預設一個執行緒的優先順序和建立他的執行緒優先順序相同;setPriority(Thread.MAX_PRIORITY)方法來設定執行緒的優先順序。
  • sleep(long millis)/sleep(longmillis, intnanos)執行緒休眠:使當執行的執行緒休眠指定時間。作用:保持物件鎖,讓出CPU,呼叫目的是不讓當前執行緒獨自霸佔該程序所獲取的CPU資源,以留一定的時間給其他執行緒執行的機會;
  • Thread.yield():讓出CPU的執行權,暫停當前執行的執行緒物件,讓同等優先順序的執行緒執行。稍微的釋放執行權一會兒,時間不會很長。
  • Thread.join():用來臨時加入執行緒執行,搶奪CPU執行權。例如:當A執行緒執行到B執行緒的Join方法時,A就會等待,等B執行緒執行完之後,A執行緒才會執行。
  • object.wait():用在同步中,如果不在鎖中使用會丟擲IllegalMonitorStateException異常。使執行緒處於阻塞狀態,是執行緒進入等待池中,釋放鎖,釋放執行權

  • object.notify()/notifyAll():喚醒在當前物件等待池中等待的第一個執行緒/所有執行緒。notify()/notifyAll()也必須擁有相同物件鎖,否則也會丟擲IllegalMonitorStateException異常。
  • Synchronizing Block:機鎖具有獨佔性、一旦被一個Thread持有,其他的Thread就不能再擁有(不能訪問其他同步方法),方法一旦執行,就獨佔該鎖,直到從該方法返回時才將鎖釋放,此後被阻塞的執行緒方能獲得該鎖,重新進入可執行狀態。

下面給出上面方法的測試程式碼:

yield(),join(),priority屬性的測試,其它方法不測試了,在是我的文章裡面可以看到:

設計兩個執行緒,一個執行緒為主執行緒,一個執行緒Thread-0:

程式碼:沒有用Join方法主執行緒和Thread-0交替的執行。大家都知道,這裡不測試了。但是用了join方法大家看效果.

join方法的原始碼:

* Waits at most {@codemillis} milliseconds for this thread to
* die. A timeout of {@code 0} means to wait forever. * * <p> This implementation uses a loop of {@code this.wait} calls * conditioned on {@code this.isAlive}. As a thread terminates the * {@code this.notifyAll} method is invoked. It is recommended that * applications not use {@code wait}, {@code notify}, or * {@code notifyAll} on {@code Thread} instances. * * @param millis * the time to wait in milliseconds * * @throws IllegalArgumentException * if the value of {@code millis} is negative * * @throws InterruptedException * if any thread has interrupted the current thread. The * <i>interrupted status</i> of the current thread is * cleared when this exception is thrown.
*/
// 加鎖當前執行緒
public final synchronized void join(long millis) throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (millis == 0) {
//A執行緒是start,在執行中 while (isAlive()) {
          //main執行緒等待 wait(0); } } else {
//join(timeOut)的情況 while (isAlive()) {
          //根據當前timeout的時間-now 是否<=0進行判斷,主執行緒是否繼續阻塞等待 long delay = millis - now;
//等待超時時間到了,則主執行緒不阻塞了,等待結束 if (delay <= 0) { break; } wait(delay);
//子執行緒從迴圈開始到現在執行的時間 now = System.currentTimeMillis() - base; } } }

給一個例子來理解:

package concurrentMy.joins;

/**
 * 
 * @author Administrator
 * 
 * main 執行緒 和 A執行緒,A執行緒是main執行緒建立並且啟動的,main執行緒優先順序比較高,正在執行;
 * 這個時候main執行緒呼叫A.join()之後,main執行緒一直等待,直到A執行緒執行完畢,main執行緒才執行
 * 
 */
class ThreadA extends Thread {
    
    public ThreadA(String name){
        super(name);
    }

    @Override
    public void run() {
       、
        for (int i = 0; i < 20; i++) {
            // 複寫父類的toString方法, 返回該執行緒的字串表示形式,包括執行緒名稱、優先順序和執行緒組。
            // Thread[Thread-1,5,main]預設的優先順序為5,優先順序從1-10
            System.out.println(Thread.currentThread().getName() + "-" + i);

        }
    }

}

public class JoinDemo {

    /**
     * @param args
     * @throws InterruptedException 
     */
    public static void main(String[] args) throws InterruptedException {
        ThreadA A = new ThreadA("執行緒A");
        A.start();
        A.join(); //A執行緒加入到“main執行緒”中,main執行緒一直等待,直到A執行緒執行完畢,main執行緒才執行
        System.out.println(Thread.currentThread().getName() + "執行");
        System.out.println(Thread.currentThread().getName() + "執行終止");

    }

}

輸出結果:

執行緒A-0
執行緒A-1
執行緒A-2
執行緒A-3
執行緒A-4
執行緒A-5
執行緒A-6
執行緒A-7
執行緒A-8
執行緒A-9
執行緒A-10
執行緒A-11
執行緒A-12
執行緒A-13
執行緒A-14
執行緒A-15
執行緒A-16
執行緒A-17
執行緒A-18
執行緒A-19
main執行
main執行終止
 

程式碼執行整個過程如下圖:

例子2,優先順序測試

package com.lp.ecjtu.Thread;
/**
 * 
 * @author Administrator
 * 當A執行緒執行到B執行緒的Join方法時,A就會等待,等B執行緒執行完之後,A執行緒才會執行
 * Join方法可以用來臨時加入執行緒執行
 */
class Join implements Runnable{

    @Override
    public void run() {
        for(int i=0;i<20;i++){
            //複寫父類的toString方法, 返回該執行緒的字串表示形式,包括執行緒名稱、優先順序和執行緒組。
            //Thread[Thread-1,5,main]預設的優先順序為5,優先順序從1-10
            System.out.println(Thread.currentThread().toString()+"-"+i);
            
        }
    }
    
}
public class JoinDemo {

    /**
     * @param args
     * @throws InterruptedException 
     */
    public static void main(String[] args) throws InterruptedException {
        Join join = new Join();
        Thread t1 = new Thread(join);
        Thread t2 = new Thread(join);
        t2.setPriority(Thread.MAX_PRIORITY);//設定執行緒的優先順序的方法
        t1.start();
        t2.start();
       
    }

}

輸出結果:

Thread[Thread-1,10,main]-0
Thread[Thread-1,10,main]-1
Thread[Thread-1,10,main]-2
Thread[Thread-1,10,main]-3
Thread[Thread-1,10,main]-4
Thread[Thread-1,10,main]-5
Thread[Thread-1,10,main]-6
Thread[Thread-0,5,main]-0
Thread[Thread-1,10,main]-7
Thread[Thread-1,10,main]-8
Thread[Thread-0,5,main]-1
Thread[Thread-1,10,main]-9
Thread[Thread-1,10,main]-10
Thread[Thread-1,10,main]-11
Thread[Thread-1,10,main]-12
Thread[Thread-1,10,main]-13
Thread[Thread-1,10,main]-14
Thread[Thread-1,10,main]-15
Thread[Thread-1,10,main]-16
Thread[Thread-1,10,main]-17
Thread[Thread-1,10,main]-18
Thread[Thread-0,5,main]-2
Thread[Thread-1,10,main]-19
Thread[Thread-0,5,main]-3
Thread[Thread-0,5,main]-4
Thread[Thread-0,5,main]-5
Thread[Thread-0,5,main]-6
Thread[Thread-0,5,main]-7
Thread[Thread-0,5,main]-8
Thread[Thread-0,5,main]-9
Thread[Thread-0,5,main]-10
Thread[Thread-0,5,main]-11
Thread[Thread-0,5,main]-12
Thread[Thread-0,5,main]-13
Thread[Thread-0,5,main]-14
Thread[Thread-0,5,main]-15
Thread[Thread-0,5,main]-16
Thread[Thread-0,5,main]-17
Thread[Thread-0,5,main]-18
Thread[Thread-0,5,main]-19

總結:從結果可以看出Thread-1,10,main優先順序為10的執行緒2先執行。

yield方法是正在執行的執行緒釋放執行權,暫停執行一小會兒。這裡不測了。。。。。。