多執行緒基礎知識

A-bird發表於2020-10-07

程式和執行緒

程式是一個應用程式;執行緒是應用程式中的執行單元。
一個程式可以由多個執行緒,最基本的包括主執行緒和垃圾回收執行緒。
一個執行緒佔一個棧空間,不同棧空間相互獨立,互不共享,堆和方法區記憶體是對這些棧是共享的。JVM記憶體結構
所以可以看出,main函式(主執行緒)結束不代表執行緒結束,因為還有其它分支執行緒進行彈棧壓棧操作。

執行緒的建立方法

1.建立一個Thread類的子類,並重寫run()方法
2.實現Runnable介面,重寫run()方法,並用new Thread(實現介面的物件)進行封裝
3.使用匿名類的形式快速實現Runnable介面,並進行封裝

執行緒的執行狀態

五種狀態:新建狀態——就緒狀態——執行狀態——阻塞狀態——死亡狀態。
new Thread()標誌著為新建狀態;
start()標誌著進入就緒狀態,又叫做可執行狀態,擁有搶奪CPU時間片的權利(執行權),當搶到了一塊CPU時間片之後,就開始執行run方法;
run()標誌著進入執行狀態,當這個時間片用完之後會再次回到就緒狀態,然後重新搶奪時間片並繼續run方法的執行(run的內容不會再次從頭開始執行);
遇到阻塞事件(使用者輸入或者sleep)標誌著進入阻塞狀態,放棄當前的時間片,回到就緒狀態重新奪取時間片;
run()的內容執行完之後就進行死亡狀態。

執行緒的sleep,interrupt和終止執行緒

sleep()函式是靜態方法,作用是對當前執行緒(所處的程式碼塊決定)進行休眠。interrupt()函式是非靜態方法,可以中斷執行緒中的休眠時間這種方式是通過Java的異常處理機制來實現的。

多執行緒併發

真正的多執行緒併發是指同一時間點有多個執行緒同時執行。對於單核CPU一次只能執行一個執行緒,系統會對多個執行緒進行排程,線上程之間來回切換,在巨集觀上看來像是在同時執行。

併發: 當有多個執行緒在操作時,如果系統只有一個CPU,則它根本不可能真正同時進行一個以上的執行緒,它只能把CPU執行時間劃分成若干個時間段,再將時間 段分配給各個執行緒執行,在一個時間段的執行緒程式碼執行時,其它執行緒處於掛起狀。.這種方式我們稱之為併發(Concurrent)。
並行: 當系統有一個以上CPU時,則執行緒的操作有可能非併發。當一個CPU執行一個執行緒時,另一個CPU可以執行另一個執行緒,兩個執行緒互不搶佔CPU資源,可以同時進行,這種方式我們稱之為並行(Parallel)。

package birda;
//建立執行緒的三種方法

public class Mythread extends Thread{		
	@Override
	public void run() {
		for(int i=0;i<1000;i++) {
			System.out.println(Thread.currentThread().getName()+"--->"+i);
		}
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//繼承Thread
		Mythread t1=new Mythread();
		t1.setName("t1執行緒");
		t1.start();
		for(int i=0;i<1000;i++) {
			System.out.println("主執行緒--->"+i);
		}
		
		try {
			Thread.sleep(1000*5);//當前執行緒睡眠;此時當前執行緒為主執行緒
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
		System.out.println("開始執行t2執行緒的內容");
		//實現Runnable介面
		Thread t2=new Thread(new MyRunnable());
		t2.setName("t2執行緒");
		t2.start();
				
		try {
			Thread.sleep(1000*5);//當前執行緒睡眠;此時當前執行緒為主執行緒
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		System.out.println("開始執行t3執行緒的內容");		
		//匿名類的形式建立執行緒
		Runnable r=new Runnable() {
			@Override
			public void run() {

				for (int i = 0; i < 10; i++) {
					System.out.println(Thread.currentThread().getName() + "--->" + i);
				}
				
				try {
					Thread.sleep(1000 * 60);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block

				}

				System.out.println("已經被睡眠60s了");

				if (Thread.interrupted()) {
					System.out.println("執行緒被中斷過");
				}
			}						
		};
		
		Thread t3=new Thread(r);
		t3.setName("執行緒t3");
		System.out.println("執行緒t3的名字為: "+t3.getName());
		t3.start();
		//中斷執行緒睡眠
		t3.interrupt();
		
		//終止執行緒
		//通過布林標記的方式終止
		MyRunnable rm=new MyRunnable();
		Thread t4=new Thread(rm);
		t3.setName("執行緒t4");
		t3.start();
		//主執行緒睡眠5秒
		try {
			Thread.sleep(100*5);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		rm.run=false;//終止t4執行緒
					
	}
}

class MyRunnable implements Runnable{
	boolean run=true;
	@Override
	public void run() {
		// TODO Auto-generated method stub
		if (run) {
			for (int i = 0; i < 10; i++) {
				System.out.println(Thread.currentThread().getName() + "--->" + i);
			}
		}else {
			//save
			return;
		}
	}
}

什麼時候開始搶奪時間片呢

start()之後,run()之前。

相關文章