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方法是正在執行的執行緒釋放執行權,暫停執行一小會兒。這裡不測了。。。。。。