Thread學習之二(線程的生命週期以及常見方法)

1. 線程的生命週期:java

  1. 建立Thread對象後調用start()方法,線程變爲可執行狀態(就緒狀態)。注意:不能對已經啓動的線程再次調用start()方法,不然會出現java.lang.IllegalThreadStateException異常。ide

  2. 線程得到CPU調度後,線程就進入Running(執行狀態)並自動調用run()方法執行方法體。this

    當運行中的線程調用yeild()方法,則該線程會讓出CPU控制權,進入Runnable狀態。但該線程有可能再次搶到CPU控制權繼續執行。spa

  3. 當線程的run()方法執行完,或者被強制終止(如調用方法:stop(),destory()),或發生Error、Exception等等,那麼這個線程就處於死亡狀態。這個線程對象也許是活的,可是它已經不是一個單獨執行的線程。若是在一個死去的線程上調用start()方法,會拋出java.lang.IllegalThreadStateException異常。.net

  4. 線程在運行過程當中遇到wait()方法,會被放入wait pool中等待。
    線程

  5. 直到有notify()、notifyAll()或interrupt()方法將它喚醒或打斷進入lock pool開始等待對象鎖。code

  6. 得到對象鎖後進入runnable狀態。對象

  7. 線程執行過程當中請求對象鎖,可是沒有得到,這時候它被放進lock pool中等待對象鎖。blog

    1. 這裏要注意一點的是,當線程調用sleep(millis)方法時,也會使線程進入Block狀態;與wait()方法不一樣的是,sleep()方法不會釋放對象鎖,睡眠時間達到後會繼續執行。生命週期

    2. wait()、notify()和notifyAll()只能在同步控制方法或同步控制塊裏面使用,而sleep()能夠在任何地方使用。參見:http://blog.csdn.net/nicklsq/article/details/7360845


2. 線程的常見方法:

1)  yield()方法:線程調用yield()方法,則該線程會讓出CPU佔有權,進入Runnable狀態。yield()方法對應了以下操做:先檢測當前是否有相同優先級的線程處於Runnable狀態,若是有,則把CPU的佔有權交給此線程,不然繼續運行原來的線程。執行yield()方法的線程有可能在進入到Runnable狀態後又立刻被執行,因此yield()方法只能是同優先級的線程有執行的機會。

  1. public class YieldThreadTest extends Thread {
    	
    	public YieldThreadTest(String threadName) {
    		super(threadName);
    	}
    	
    	@Override
    	public void run() {
    		for (int i = 0; i < 100; i++) {
    			System.out.println(getName() + ": " + i);
    			
    			if (i == 10) {
    				yield(); //使當前線程變爲可執行狀態(讓出CPU控制權),但有可能再次搶到CPU控制權
    			}
    		}
    	}
    	
    	public static void main(String[] args) {
    		Thread t1 = new YieldThreadTest("線程-1");
    		Thread t2 = new YieldThreadTest("線程-2");
    		
    		t1.start();
    		t2.start();
    	}
    }

2)  sleep()方法:使當前調用該方法的線程暫停執行一段時間,讓其餘線程有機會執行,但它並不釋放對象鎖。若是有synchronized同步代碼塊,其餘線程仍然不能訪問共享數據。例如:有兩個線程同時執行(沒有synchronized),一個線程的優先級爲MAX_PRIORITY,另外一個爲MIN_PRIORITY,若是沒有Sleep()方法,只有高優先級的線程執行完畢後,低優先級的線程纔可以執行;可是高優先級的線程sleep(500)後,低優先級就有機會執行了。

  1. public class PrintNumber extends Thread {
    	int i = 0;
    	
    	public static void main(String[] args) {
    		
    		PrintNumber printNumber = new PrintNumber();
    		
    		NumberThread thread1 = new NumberThread("線程-1", printNumber);
    		NumberThread thread2 = new NumberThread("線程-2", printNumber);
    		
    		thread1.setPriority(MAX_PRIORITY);
    		thread2.setPriority(MIN_PRIORITY);
    		
    		thread1.start();
    		thread2.start();
    	}
    }
    
    class NumberThread extends Thread{
    	PrintNumber printNumber;
    	
    	public NumberThread(String threadName, PrintNumber printNumber) {
    		super(threadName);
    		this.printNumber = printNumber;
    	}
    	
    	@Override
    	public void run() {
    		for (; printNumber.i < 100; printNumber.i++) {
    //			if (printNumber.i % 10 == 0) {
    //				try {
    //					sleep(1000);
    //				} catch (InterruptedException e) {
    //					e.printStackTrace();
    //				}
    //			}
    			
    			System.out.println(getName() + ": " + printNumber.i);
    		}
    	}
    }

       運行結果:a. thread1 一直執行到結束  b. 取消註釋部分,thread一、thread2交替打印

3)  join()方法:使調用該方法的線程執行完畢後,在往下繼續執行。

  1. public class JoinThreadTest extends Thread {
    	
    	public static void main(String[] args) {
    		Thread thread = new JoinThreadTest();
    		thread.start();
    		
    		for (int i = 0; i < 100; i++) {
    			System.out.println(Thread.currentThread().getName() + ": " + i);
    			
    			if (i == 10) {
    				try {
    					thread.join();
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    	}
    	
    	@Override
    	public void run() {
    		for (int i = 0; i < 100; i++) {
    			System.out.println(Thread.currentThread().getName() + ": " + i);
    		}
    	}
    }
相關文章
相關標籤/搜索