多線程

什麼是進程?

I. 進程是具有獨立功能的程序在某個數據集合上的一次執行過程。進程是系統進行資源分配和調度的一個獨立單位。
II. 通俗的講進程就是:運行中的程序,稱爲進程。
III. 需要知道的是:單核CPU在任一時間點上,只能運行一個程序。
IV.進程宏觀上是並行,微觀上是串行。

什麼是線程?

I. 線程是進程內的一個執行實體或執行單元,是比進程更小的能獨立運行的基本單位。 線程實質上也是一個輕量級進程。
II. 程序中的一個順序執行流程,也是CPU的基本調度單位。

進程與線程的區別:

操作系統引入線程機制後,進程是資源分配和調度的單位,線程是處理機調度和分配的單位,資源分配給進程,線程只擁有很少資源,線程切換代價比進程低。不同進程地址空間相互獨立,同一進程內的線程共享同一地址空間。一個進程的線程在另一個進程內是不可見的。創建進程或撤銷進程,系統都要爲之分配或回收資源,操作系統開銷遠大於創建或撤銷線程時的開銷。

多線程

I. 進程可以由單個或多個線程組成,彼此間完成不同的工作,交替執行,稱爲多線程。
II. JVM虛擬機是一個進程,默認包含主線程(Main函數),可以通過代碼創建多個獨立線程,與Main線程併發執行。

線程的組成

I.CPU時間片
II. 運行數據:
(1).堆空間:存儲線程需要使用的對象,多個線程可以共享堆中的對象
(2).棧空間:存儲線程需要使用的局部變量,每個線程都擁有獨立的棧

線程的創建

I. 繼承Thread類,自定義類變成線程類

public class TestThread {
	public static void main(String[] args) {
		
		Thread t = new T();//父類引用指向子類對象,創建了線程對象t
		t.start();//啓動線程
	}
}

class T extends Thread{
	public void run(){//覆蓋run()方法
		System.out.println("T extends Thread");
	}
}

II. 實現Runnable接口,賦予自定義類線程任務的能力。

public class TestRunnable {
	public static void main(String[] args) {
		T2 t = new T2(); //創建實現類對象
		Thread t2 = new Thread(t);//創建線程對象 
		t2.start();//通過線程對象.start()方法啓動線程
	}
}	
class T2 implements Runnable{

	@Override
	public void run() {//覆蓋run()方法
		System.out.println("T2 implements Runnable");
	}
	
}

使用Runnable接口可以更方便的表示出數據共享的概念

線程的基本狀態

在這裏插入圖片描述

線程中常用方法

I.休眠 sleep(long millis);
(1).當前線程主動休眠 millis毫秒,進入有限期等待!

public class TestThread {
	public static void main(String[] args) {
		
		Thread t = new T();
		t.start();
	}
}

class T extends Thread{
	public void run(){
		try {
			Thread.sleep(2000);//調用sleep()方法 讓當前線程等待兩千豪秒(兩秒)
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("T extends Thread");
	}
}

II. 放棄 yield();
(1).當前線程主動放棄時間片,回到就緒狀態,競爭下一次時間片

public class TestThread {
	public static void main(String[] args) {
		
		Thread t = new T();
		t.start();
		for(int i = 1 ; i < 6 ; i++){
			System.out.println("main"+"---"+i);
		}
		
	}
}

class T extends Thread{
	public void run(){
		for(int i = 1 ; i < 6 ; i++){
			Thread.yield();//當前線程主動放棄時間片,回到就緒狀態,競爭下一次時間片

			System.out.println("T extends Thread"+"---"+i);
		}
	}
}

III. 結合 join();
(1).允許其他線程加入到當前線程中,當前線程進入無限期等待!

public class TestThread {
	public static void main(String[] args) {
		
		Thread t = new T();
		t.start();
		for(int i = 1 ; i < 6 ; i++){
			System.out.println("main"+"---"+i);
		}
		
	}
}

class T extends Thread{
	public void run(){
		for(int i = 1 ; i < 6 ; i++){
			try {
				this.join();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("T extends Thread"+"---"+i);
		}
	}
}

在這裏插入圖片描述
從運行結果可以看出程序並未結束,而是由於join()的加入,導致T一直在等待,即無限期等待

線程的等待狀態

在這裏插入圖片描述

線程安全

I.同步代碼塊
(1). synchronized(臨界資源對象){
//原子操作
}
II.同步方法
(1). synchronized 返回值類型 方法名成(參數列表){
//原子操作
}

注意:
synchronized  同步鎖
I.每個對象都有一個互斥鎖標記,用來分配給線程。
II.只有持有對象互斥鎖標記的線程,才能進入對該對象加鎖的同步操作中(同步方法、同步代碼塊)。
III.只有線程退出同步操作時,纔會釋放相應的鎖標記
同步的規則:
I.只有在調用包含同步代碼塊的方法或者是同步方法時,才需要對象的鎖標記
II.如果調用的是不包含同步代碼塊的方法或普通方法時,則不需要鎖標記,直接調用即可。

線程的阻塞狀態

在這裏插入圖片描述

線程的通信

I.等待
(1)wait();
(2) 必須在對obj(對象)加鎖的同步代碼塊(或同步方法)中,在一個線程執行期間,調用了obj.wait(),該線程會釋放所擁有的鎖標記。同時,進入到obj的等待隊列中。等待喚醒
II. 通知(喚醒)
(1).notify();//喚醒其中一個線程
notifyAll();//喚醒所有的線程
(2).必須在對obj加鎖的同步代碼塊(或同步方法)中,從obj的Waiting(等待隊列)中隨機釋放一個或全部線程。對自身線程無影響。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章