天天看點

多線程基礎知識以及常用方法多線程

多線程

一、什麼是程序

程序是系統進行資源配置設定和調用的獨立單元,每一個程序都有它的獨立記憶體空間和系統資源。

二、單程序作業系統和多程序作業系統的差別

單程序作業系統 dos:一次隻能執行單個任務

多程序作業系統 Windows:一次可以執行多個任務

三、系統在同一個時刻可以執行多個任務嗎?

理論上,同一個時刻可以執行多個任務。

因為CPU切換比較快,有的程序正在運作,有的程序正在争搶資源,有的程序正在退出資源

四、什麼是線程,了解線程和程序的關系

什麼是線程?

線程是程序裡面的一條執行路徑,每個線程同享程序裡面的記憶體空間和系統資源

一個程序裡有多線程:各個線程都有不同的分工

了解線程和程序的關系?

程序:程序之間的記憶體空間和系統資源是獨立的

線程:在同一個程序裡的線程之間是共享記憶體空間和系統資源的

程序裡:可以有一條或一條以上的線程

注意:

程序裡隻有一條線程的情況下,這條線程就叫做主線程

程序裡有多條線程的情況下,隻有一條線程叫做主線程

線程是在程序裡的,他們是包裹關系

五、我們應用的軟體有哪些是多線程的應用?

幾乎都是

六、Java中,如何來編寫多線程的應用程式?有哪些方法?

  1. 線程類

建立步驟:建立MyThread類,繼承Thread,重寫run方法

使用步驟:建立MyThread類的對象,調用start方法

  1. 任務類

建立步驟:建立Task類,實作Runnable接口,重寫run方法

使用步驟:建立Thread類的對象,并把任務類的對象傳入,調用start方法

  1. 帶傳回值的任務類
  2. 線程池

七、體會多線程争搶資源的場景

需求:編寫一個多線程的應用程式,主線程列印1-100之間的數字,子線程列印200-300之間的數字,觀察其輸出的結果,體會多線程互相争搶資源的場景

八、小結

線程類:繼承Thread,重寫run方法,建立線程對象,調用start方法(并非馬上調用run方法)

任務類:實作Runnable接口,重寫run方法,建立任務類對象,通過new Thread(task).start()

主線路從上往下,多線程多條執行路線(随機)

經典面試題:請問當我們編寫一個單純的main方法時,此時該程式是否為單線程的?為什麼?

Java的垃圾回收器是一個背景線程,默默在背景銷毀多餘的對象

九、線程的優先級

需求:在主線程中建立三個的子線程,并且設定不同優先級,觀察其優先級對線程執行結果的影響。

注意:

  1. 優先級别10-1,10是最進階别,1是最低級别
  2. 設定優先級别隻能影響結果,不能決定結果
package com.dream.thread04;

public class Test01 {
	
	public static void main(String[] args) {
		/**
		 * 線程的優先級别
		 */
		
		//建立線程對象
		A a = new A();
		B b = new B();
		C c = new C();
		
		//設定優先級别
		a.setPriority(Thread.MAX_PRIORITY);//最進階别:10
		b.setPriority(Thread.NORM_PRIORITY);//預設級别:5
		c.setPriority(Thread.MIN_PRIORITY);//最低級别:1
		
		//啟動線程
		a.start();
		b.start();
		c.start();
	}
}
           

十、給線程自定義名稱

package com.dream.thread05;

public class MyThread extends Thread{
	
	public MyThread(String name) {
		super(name);
	}

	@Override
	public void run() {
		for (int i = 1; i <= 100; i++) {
			//Thread.currentThread():擷取目前線程對象
			System.out.println(Thread.currentThread().getName() + ":" + i);
		}
	}
}
           

十一、線程的休眠

Thread.sleep(1000);休眠目前線程,該方法在哪個線程中調用,就休眠哪個線程

需求: 編寫一個抽取學員回答問題的程式,要求倒數三秒後輸出被抽中的學員姓名

package com.dream.thread06;

import java.util.Random;

public class Test01 {
	
	public static void main(String[] args) throws InterruptedException {
		/**
		 * 線程的休眠
		 * 需求: 編寫一個抽取學員回答問題的程式,要求倒數三秒後輸出被抽中的學員姓名
		 */
		
		Random ran = new Random();
		String[] names = {"麻生希","曹桂華","椎名空","北島玲","水菜麗"};
		String name = names[ran.nextInt(names.length)];
		
		for (int i = 3; i > 0; i--) {
			System.out.println(i);
			Thread.sleep(1000);
		}
		
		System.out.println(name);
	}
}
           

十二、線程的禮讓

Thread.yield(); 禮讓,寫在哪個線程裡,哪個線程就退出CPU資源,馬上進入到争搶資源的狀态

需求:建立兩個線程A,B,分别各列印100次,從1開始每次增加1,其中B一個線程,每列印一次,就禮讓一次,觀察實驗結果

十三、線程的合并

需求:主線程和子線程各列印200次,從1開始每次增加1,當主線程列印到10之後,讓子線程先列印完再列印主線程

十四、線程的中斷

方式1:自己編寫邏輯使得線程中斷

方式2:

​ Thread.currentThread().isInterrupted() – 判斷目前線程是否消亡

​ t.interrupt(); – 改變目前線程狀态

十五、守護線程

含義:守護線程又叫做背景線程,默默守護着前台線程,所有的前台線程消亡後,守護線程自動消亡

注意:垃圾回收器就是一個守護線程

十六、線程局部變量(實作線程範圍内的共享變量)

1.自定義一個靜态變量用于共享

//用靜态變量 concurrenthashMap 作為線程間共享的變量,存儲單個值

//其他類可以通過類名直接擷取,達到共享,通過誰調用就擷取到目前調用線程的對象來存放值。

//線程類通過map,将自己作為key,i作為值放入map

//普通類被線程類的run方法調用,執行成員方法時可以擷取到目前類對象,進而通過map,直接擷取到值。并輸出列印

2.ThreadLocal

低層也是用一個map 來存放資料,通過get()、set()方法擷取或者設定變量,内部是通過Thread.concurrentThread()方法擷取目前線程對象,将目前線程對象作為key,傳入值作為value;

擷取時也是擷取調用線程所對應的key和value

十七、線程的生命周期

a) 建立狀态

i. 在程式中用構造方法建立了一個線程對象後,新的線程對象便處于建立狀态,此時,它已經有了相應的記憶體空間和其它資源,但還處于不可運作狀态。建立一個線程對象可采用線程構造方法來實作。

ii. 例如:Thread thread=new Thread();

b) 就緒狀态

i. 建立線程對象後,調用該線程的start()方法就可以啟動線程。當線程啟動時,線程進入就緒狀态。此時,線程将進入線程隊列排隊,等待CPU調用,這表明它已經具備了運作條件。

c) 運作狀态

i. 當就緒狀态的線程被調用并獲得處理器資源時,線程就進入了運作狀态。此時,自動調用該線程對象的run()方法。run()方法定義了該線程的操作和功能。

d) 阻塞狀态

i. 一個正在執行的線程在某些特殊情況下,如被人為挂起,将讓出CPU并暫時中止自己的執行,進入阻塞狀态。在可執行狀态下,如果調用sleep(2000)、wait()等方法,線程都将進入阻塞狀态。阻塞時,線程不能進入排隊隊列,隻有當引起阻塞的原因被消除後,線程才可以轉入就緒狀态。

e) 死亡狀态

i. 線程調用stop()方法時或run()方法執行結束後,線程即處于死亡狀态。處于死亡狀态的線程不具有繼續運作的能力。

線程的生命周期

多線程基礎知識以及常用方法多線程

Thread.currentThread().isInterrupted();

//判斷目前線程是否被中斷,true-中斷 false-未中斷

//通過Thread類的一個boolean 屬性來判斷目前線程 而不是真正意義上的 中斷

//

Thread.currentThread().interrupt();

修改目前線程的中斷狀态;