1. 程式人生 > >多執行緒初識

多執行緒初識

       先了解什麼是應用程式,應用程式就是類似qq,360可執行的應用程式,在一個應用程式中,都會有程序。

什麼是程序,程序中有多個不同的執行路徑,多個執行緒的集合。程序是執行中的程式。

什麼是執行緒,一個執行順序,一個執行流程,執行路徑。每個執行緒互不影響,因為都在自己獨立執行。

總結:程序就是執行的程式,它是執行緒的集合,執行緒就是獨立執行的一條執行路徑。什麼是多執行緒?就是為了提高程式的效率

下面圖片比較好了解,一個程序有多個執行緒會提高效率、

 

 

執行緒的兩個分類

守護執行緒和非守護執行緒,守護執行緒(使用者執行緒)隨著主執行緒一起消失,而非守護執行緒不會被影響到。

多執行緒的狀態:

多執行緒執行狀態

http://www.blogjava.net/images/blogjava_net/santicom/360%E6%88%AA%E5%9B%BE20110901211600850.jpg

 執行緒從建立、執行到結束總是處於下面五個狀態之一:新建狀態、就緒狀態、執行狀態、阻塞狀態及死亡狀態。

新建狀態

   當用new操作符建立一個執行緒時, 例如new Thread(r),執行緒還沒有開始執行,此時執行緒處在新建狀態。 當一個執行緒處於新生狀態時,程式還沒有開始執行執行緒中的程式碼

就緒狀態

一個新建立的執行緒並不自動開始執行,要執行執行緒,必須呼叫執行緒的start()方法。當執行緒物件呼叫start()方法即啟動了執行緒,start()方法建立執行緒執行的系統資源,並排程執行緒執行run()方法。當start()方法返回後,執行緒就處於就緒狀態。

     處於就緒狀態的執行緒並不一定立即執行run()方法,執行緒還必須同其他執行緒競爭CPU時間,只有獲得CPU時間才可以執行執行緒。因為在單CPU的計算機系統中,不可能同時執行多個執行緒,一個時刻僅有一個執行緒處於執行狀態。因此此時可能有多個執行緒處於就緒狀態。對多個處於就緒狀態的執行緒是由Java執行時系統的執行緒排程程式(thread scheduler)來排程的。

執行狀態

當執行緒獲得CPU時間後,它才進入執行狀態,真正開始執行run()方法.

阻塞狀態

    執行緒執行過程中,可能由於各種原因進入阻塞狀態:
        1>執行緒通過呼叫sleep方法進入睡眠狀態;
        2>執行緒呼叫一個在I/O上被阻塞的操作,即該操作在輸入輸出操作完成之前不會返回到它的呼叫者;
        3>執行緒試圖得到一個鎖,而該鎖正被其他執行緒持有;
        4>執行緒在等待某個觸發條件;
 

死亡狀態

有兩個原因會導致執行緒死亡:
  1) run方法正常退出而自然死亡,
   2) 一個未捕獲的異常終止了run方法而使執行緒猝死。
  為了確定執行緒在當前是否存活著(就是要麼是可執行的,要麼是被阻塞了),需要使用isAlive方法。如果是可執行或被阻塞,這個方法返回true; 如果執行緒仍舊是new狀態且不是可執行的, 或者執行緒死亡了,則返回false.

 

執行緒的建立方式

package com.mydream.cn;
/**
 * 
* @Title: ThreadDemo.java  
* @Package com.mydream.cn  
* @Description: 繼承方式 實現多執行緒
* @author licl 
* @date 2018年7月25日
 */
class Demo extends Thread{
	@Override
	public void run() {
		
		for(int i=0;i<=30; i++){
			System.out.println("繼承  "+i);
		}
		
	}
}
/**
 * 
* @Title: ThreadDemo.java  
* @Package com.mydream.cn  
* @Description: 實現runnable 介面方式
* @author licl 
* @date 2018年7月25日
 */
class RunnableDemo implements Runnable{

	@Override
	public void run() {
		for(int j=0;j<=30; j++){
			System.out.println("實現  "+j);
		}
	}
	
}
public class ThreadDemo {

	public static void main(String[] args) {
		// 繼承
		Demo demo = new Demo();
		demo.start();
		
		// 實現
		Thread thread  = new Thread(new RunnableDemo());
		thread.start();
		
		// 主函式的
		for(int j=0;j<=30; j++){
			System.out.println("main  "+j);
		}
		
		// 匿名內部類方式實現
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				for(int j=0;j<=30; j++){
					System.out.println("內部類  "+j);
				}
			}
		}){}.start();;
		
		
	}
}

 1,繼承Thread類

 2,實現Runnable介面

 

簡單的說一下Thread的join方法

把指定的執行緒加入到當前執行緒,可以將兩個交替執行的執行緒合併為順序執行的執行緒。
比如線上程B中呼叫了執行緒A的Join()方法,直到執行緒A執行完畢後,才會繼續執行執行緒B。   重點掌握

 

 

package com.mydream.cn;




class DemoJoin implements Runnable {
	@Override
	public void run() {
		for (int i = 0; i <= 3; i++) {
			System.out.println("子執行緒    " + i);
		}
	}
}

public class ThreadJoin {

	 public static void main(String[] args) throws InterruptedException {
	 Thread thread = new Thread(new DemoJoin());
	 thread.start();
	 // Thread.currentThread().join();
	 thread.join();
	 for(int i=0;i<=3;i++){
	 System.out.println("主    "+i);
	 }
	
	
	}
}

結果圖 

 

 

經典面試題

 現在有T1、T2、T3三個執行緒,你怎樣保證T2在T1執行完後執行,T3在T2執行完後執行 

 

package com.mydream.cn;
// 要求 執行順序為 t1   t2  t3
class DemoJoin implements Runnable {
	@Override
	public void run() {
		for (int i = 0; i <= 3; i++) {
			System.out.println("子執行緒    " + i);
		}
	}
}
public class ThreadJoin {
	public static void main(String[] args) throws InterruptedException {
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				for (int i = 0; i <= 10; i++) {
					System.out.println("111    " + i);
				}
			}
		});
		t1.start();
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				
				try {
					t1.join();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
				for (int i = 0; i <= 10; i++) {
					System.out.println("2    " + i);
				}
			}
		});
		t2.start();
		Thread t3 = new Thread(new Runnable() {
			@Override
			public void run() {
				
				try {
					t2.join();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				for (int i = 0; i <= 10; i++) {
					System.out.println("3    " + i);
				}
			}
		});
		t3.start();
	}
}	

 重點理解join放的位置,理解join的含義。