主線程:
主線程即main線程,main方法是程式的入口,執行main方法時,JVM會找到作業系統開辟一條main方法通向CPU的執行路徑,CPU就可以通過該路徑來執行main方法。同樣的道理,當我們在main方法中開啟了新的線程時,JVM也會開辟新的路徑通向CPU,讓CPU可以通過新的路徑執行新的線程任務。且在JVM中,線程的排程是搶占式排程,即哪一個線程的優先度高,就執行哪個線程。
了解Thread:

Thread中常用的方法:
public void start() :導緻此線程開始執行; Java虛拟機調用此線程的run方法。
public String getName() :擷取目前線程名稱。
public void setName() :設定此線程的名稱,等同于在子類中使用帶參的構造方法 Thread(String name)。
public void run() :此線程要執行的任務在此處定義代碼。
public static void sleep(long millis) :使目前正在執行的線程以指定的毫秒數暫停(暫時停止執行)。
public static Thread currentThread() :傳回對目前正在執行的線程對象的引用。
對于上面的兩個靜态方法,直接使用Thread.方法()進行調用
第一種方式:建立一個類并繼承類Thread:
java.lang.Thread類:是描述線程的類,要想實作多線程,就必須繼承Thread類
實作步驟:
1.建立一個Thread類的子類
2.在該子類中重寫run方法,設定線程任務(即設定該線程做什麼)
3.建立該子類對象
4.子類對象調用Thread類中的start方法,開啟新的線程,此時就會自動執行子類中的run方法
注意:若此時子類對象直接調用run方法,那麼是不會開啟新的線程的。
第二種方式:建立一個類并實作接口Runnable:
Runnable
接口應該由那些打算通過某一線程執行其執行個體的類來實作。類必須定義一個稱為 run
的無參數方法。
1.建立一個Runable接口的實作類
2.在該實作類中重寫Runable接口的run()方法,設定線程任務(即設定該線程做什麼)
3.建立一個實作類對象
4.建立一個Thread對象,在構造方法中傳遞實作類對象作為參數
5.Thread對象調用start()方法,開啟新線程執行run()方法
注意:實作了Runable接口後,依然需要Thread類去調用start()方法,才能開啟新線程。即Runnable實作類隻負責設定線程任務,
而開啟新線程的任務就交給了Thread類去完成,也就是實作了解耦。
知識點:
1.public class Thread extends Objectimplements Runnable :Thread類其實也是實作了Runable接口
2.通過實作Runnable接口,使得該類有了多線程類的特征。run()方法是多線程程式的一個執行目标。所有的多線程
代碼都在run方法裡面。Thread類實際上也是實作了Runnable接口的類。
3.在啟動的多線程的時候,需要先通過Thread類的構造方法Thread(Runnable target) 構造出對象,然後調用Thread
對象的start()方法來運作多線程代碼。
4.實際上所有的多線程代碼都是通過運作Thread的start()方法來運作的。是以,不管是繼承Thread類還是實作
Runnable接口來實作多線程,最終還是通過Thread的對象的API來控制線程的,熟悉Thread類的API是進行多線程
程式設計的基礎。
使用Runable開啟新線程的好處:
1.避免單繼承的局限性:如果一個類繼承了Thread類,就不能再繼承其他類了。因為在java中,一個類隻能有一個父類,而實作的接口卻可以有很多個。
2.增強程式的拓展性:實作了Runable接口後,就把設定線程任務和開啟新線程進行了分離,即實作了程式的解耦
第二種方式示例:
// 1.建立一個實作類,實作Runnable接口
public class MyRunnable implements Runnable {
// 2.重寫run()方法
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("你愛我,我愛你,蜜雪冰城甜蜜蜜"+i);
}
}
}
public class TestMyRunnable {
public static void main(String[] args) throws InterruptedException {
// 3.建立實作類對象
MyRunnable mr = new MyRunnable();
// 4.建立Thread對象,并把實作類對象傳遞給其構造方法做參數
Thread thread = new Thread(mr);
// 5.thread調用start方法,開啟新的線程
thread.start();
// 調用getName()方法
String name1 = thread.getName();
System.out.println(name1);//Thread-0
// 開啟main線程
for (int i = 0; i < 10; i++) {
System.out.println("鴻星爾克好樣的!"+i);
}
//調用currentThread()方法
String name2 = Thread.currentThread().getName();//main
//調用sleep()方法,睡眠2秒鐘
Thread.sleep(2000);
System.out.println(name2);
}
}
我們發現上面的實作類其實可以用匿名内部類來實作。
使用匿名内部類:
public class NoNameInnerClass {
public static void main(String[] args) {
// 1.使用匿名内部類,建立Runnable對象,并重寫run()方法
Runnable mr = new Runnable() { //多态,子類對象指向父類。因為此時new Runnable(){}就相當于一個Runnable的實作類
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("河南加油!!!"+i);
}
}
};
// 2.建立Thread對象,并把Runnable對象傳遞給Thread對象
Thread mt = new Thread(mr);
// thread調用start()方法,開啟新線程
mt.start();
}
}