1. 程式人生 > >java之執行緒建立的兩種方式,六種狀態和匿名內部類建立子類或實現類物件

java之執行緒建立的兩種方式,六種狀態和匿名內部類建立子類或實現類物件

一.匿名內部類建立子類或實現類物件

 new Test(){}
 相當於建立了Test類的子類物件
 並且沒有類名

建立介面實現類
new 介面名() {};介面實現類的物件

注意 : new 後邊是類或者介面名 大括號內是類或者介面中的方法

public class Kll {
	public static void main(String[] args) {
		Test test = new Test() {
			@Override
			public void fun() {
				System.out.println("重寫fun方法");
			}
		};
		test.fun();
		
		// 建立介面實現類
		// new InterA() {};介面實現類的物件
		// 注意 : new 後邊是類或者介面名
		// 大括號內是類或者介面中的方法
		InterA a = new InterA() {
			
			@Override
			public void fun() {
				System.out.println("介面實現類方法");
			}
		};
		a.fun();
		// 匿名內部類直接呼叫方法
		new InterA() {
			
			@Override
			public void fun() {
				System.out.println("哈哈哈哈哈");
			}
		}.fun();;
	}
	
}

class Test{
	
	public void fun() {
		System.out.println("Test類中的fun方法");
	}
}

interface InterA{
	public abstract void fun();
}

二.多執行緒

標準單執行緒程式

  • 好處:程式碼安全

  • 弊端:執行效率低 多執行緒

  • 程序:一個正在執行的程式就是一個程序

  • 一個程序可以有一個或多個執行緒
    
  • 執行緒:執行的任務

  • 分時排程:

    • CPU同一時間,只能執行一個任務(CPU單核單執行緒的原因)
    • 現在要同時執行多個任務
    • 這時CPU就會為這幾個任務開闢相應獨立的執行路徑
    • (執行路徑 執行功能的程式碼)
      
    • CPU會在多個任務之間進行快速切換
    • 搶佔資源:搶奪CPU的執行資源,改變任務的優先順序
  • 多執行緒好處:

    • 提高任務的執行效率(執行緒本身也會消耗系統資源,建立執行緒要把握一個度,不是越多越好)
 main呼叫
	  1.jvm呼叫main函式1.jvm呼叫main函式
	  2.CPU就為main凱比一個獨立的執行路徑
	  3.這個路徑就執行main中的程式碼3.這個路徑就執行main中的程式碼
 程式只有一個主執行緒,除了主執行緒,其他的都叫子執行緒
 這個主執行緒的名字就叫main
  • 執行緒的名字:
    • 主執行緒:main* 主執行緒:main
    • 子執行緒:預設 Thread-x(x從0開始)* 子執行緒:預設 Thread-x(x從0開始)

建立方式:

  • 執行緒建立方式1(繼承Thread類,重寫run方法)

  • 執行緒建立方式2(使用Runnable介面建立執行緒)

  • 建立放式1:繼承方式

    • 1.增加類和類的耦合度
    • 2.java中,類只能單繼承

執行緒開啟方法:start()方法。 執行的任務就是重寫run方法。 run方法和start方法的區別: 1.直接呼叫run方法,就是相當於呼叫成員方法 2. 直接呼叫start 開啟執行緒(建立獨立執行路徑) 3.執行緒中執行的任務 是run方法中的程式碼

public class Kll {
	public static void main(String[] args) {
		// 異常發生在 主執行緒中
		// 建立子執行緒
		SubThread t1 = new SubThread();
		// 開啟執行緒
		// 執行的任務就是重寫run方法
		t1.start();
		
		SubThread t2 = new SubThread();
		t2.start();
		
		for (int i = 0; i < 50; i++) {
			System.out.println("main---" + i);
		}
		System.out.println("main");
	}
}

// 建立子執行緒類
class SubThread extends Thread{
	// 重寫run方法
	@Override
	public void run() {
		//System.out.println(10 / 0);
		for (int i = 0; i < 50; i++) {
			System.out.println("run---" + i);
		}
	}
}

獲取當前執行緒名字和給執行緒設定名字:

public class Kll extends Thread{
	public static void main(String[] args) {
		NameThread n1 = new NameThread("哈哈");
		n1.setName("啾啾");
		n1.start();
		NameThread n2 = new NameThread();
		n2.start();
		
		// 獲取當前正在執行的執行緒物件
		// 放在哪兒個執行緒中,就表示哪兒個執行緒物件
		Thread thread = Thread.currentThread();
		// 列印主執行緒名字
		System.out.println(thread.getName());
	}

}


class NameThread extends Thread{
	
	// 構造方法
	public NameThread() {
		// TODO Auto-generated constructor stub
	}
	public NameThread(String name) {
		
		super(name);
	}
	
	// 重寫run方法
	@Override
	public void run() {
		for (int i = 0; i < 50; i++) {
			//獲取執行緒的名字
			//System.out.println(this.getName() + "--" + i);
			System.out.println(Thread.currentThread().getName() + "++" + i);
		}
		
	}
}
父類使用了final修飾set/get方法 ,子類不能重寫
可以使用不同的方法名來解決
執行緒在記憶體中的表現符合棧記憶體特點 : 先進後出。
 NameTread ta = new NameTread();開闢了一個新棧(相當於CPU獨立執行空間)。
 ta.start();必須呼叫開啟執行緒方法,這個棧才能執行程式碼。
 執行的程式碼就是執行緒類中run方法。
  • 建立方式2:實現方式
    • 1.介面可以多實現(靈活)
    • 2.將執行緒要執行的方法從類中分離出來
public class Kll {
	public static void main(String[] args) {
		// 建立介面實現類物件
		RunnableImpl ruImpl = new RunnableImpl();
		// 建立執行緒類物件
		Thread t = new Thread(ruImpl);
		// 開啟執行緒
		t.start();
	}

}

class RunnableImpl implements Runnable{

	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName());
		
	}
	
}
  • 匿名內部類 建立執行緒程式碼:
public class Kll {
	public static void main(String[] args) {
		// 執行緒類的子類建立
		Thread t1 = new Thread() {
			@Override
			public void run() {
				System.out.println("執行緒子類的run方法");
			}
		};
		t1.start();
		
		// 介面類的實現類建立執行緒
		Runnable r1 = new Runnable() {
			
			@Override
			public void run() {
				System.out.println("介面實現類");
				
			}
		};
		// 建立執行緒物件
		Thread t2 = new Thread(r1);
		t2.start();
		
		// 合併一起
		Thread t3 = new Thread(new Runnable() {
			
			@Override
			public void run() {
				System.out.println("介面實現類和執行緒物件合併");
				
			}
		});
		t3.start();
		
	}

}

三.執行緒的六種狀態

  • 執行緒休眠方法(測試時常用)。

    • sleep(long time);單位毫秒;效果:卡住你當前的執行緒
    • 注意: 書寫的位置,決定休眠哪兒個執行緒。
  • 執行緒的6種狀態:

    • new 新建狀態
    • runnable 執行狀態
    • blocked 受阻塞狀態
    • waiting 等待狀態
    • timed waiting 休眠狀態
    • terminated 死亡狀態
  • 執行緒呼叫了start方法 就一定會進入執行狀態嗎?

    • 不會,必須得到CPU的資源才會進入執行狀態。
      • 執行緒呼叫了start方法而是得到了CPU的執行權。
      • 沒有得到CPU執行資源的執行緒,會進入受阻塞狀態。
      • 當受阻塞狀態的執行緒得到了CPU的執行資源,這是會從受阻塞—>執行狀態。
  • 執行狀態–>休眠狀態 相當於放棄了 CPU的執行權

  • 等休眠時間結束 重新獲得CPU的執行權

  • 等到用notify()方法 重新獲得CPU的執行權

  • 注意 :wait()和notify()方法是Object類中的方法

六種狀態轉換圖:在這裡插入圖片描述 執行緒休眠程式碼: 注意 : 父類中的run方法沒有丟擲異常 子類中只能自己處理(try…catch)

public class Demo10 {
	public static void main(String[] args) throws InterruptedException {
		// 執行緒休眠
		// 單位毫秒
		// 效果:卡住你當前的執行緒
		// 注意: 書寫的位置,決定休眠哪兒個執行緒
		Thread.sleep(1000);
		System.out.println("main");
		
		TestBThread tb = new TestBThread();
		tb.start();
	}

}

class TestBThread extends Thread {
	@Override
	public void run() {
		for (int i = 0; i < 50; i++) {
			// 休眠一秒
			// 注意 : 父類中的run方法沒有丟擲異常
			// 子類中只能自己處理(try...catch)
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "--" + i);
			
		}
	}
}