java 多執行緒-1
阿新 • • 發佈:2020-09-11
一、程式、程序、執行緒簡介
程式(program)是為完成特定任務、用某種語言編寫的一組指令的集合。即指一段靜態的程式碼,靜態物件
程序(process)是程式的一次執行過程,或是正在執行的一個程式。是一個動態的過程:有它自身的產生、存在和消亡的過程。——生命週期
- 如:執行中的QQ,執行中的MP3播放器
- 程式是靜態的,程序是動態的
- 程序作為資源分配的單位,系統在執行時會為每個程序分配不同的記憶體區域
執行緒(thread),程序可進一步細化為執行緒,是一個程式內部的一條執行路徑。
若一個程序同一時間並行執行多個執行緒,就是支援多執行緒的
執行緒作為排程和執行的單位,每個執行緒擁有獨立的執行棧
和程式計數器(pc),執行緒切換的開銷小。
- 棧和程式計數器,每個執行緒各自有一套
- 方法區、堆一個程序一份,一個程序裡面有個多個執行緒,這也就意味這,多個執行緒共享方法區和堆。
- 一個程序中的多個執行緒共享相同的記憶體單元/記憶體地址空間它們從同一堆中分配物件,可以訪問相同的變數和物件。這就使得執行緒間通訊更簡便、高效。但多個執行緒操作共享的系統資源可能就會帶來安全的隱患。
二、並行與併發
並行:多個CPU同時執行多個任務。比如:多個人同時做不同的事。
併發:一個CPU(採用時間片)同時執行多個任務。比如:秒殺、多個人做同一件事。
三、執行緒的建立方式一 【繼承Thread類】
Thread類的特性。
- 每個執行緒都是通過某個特定Thread物件的run()方法來完成操作的,經常把run()方法的主體稱為執行緒體。
- 通過該Thread物件的start()方法來啟動這個執行緒,而非直接呼叫run()。【直接調動run方法不是多執行緒】
Thread類構造器
- Thread():建立新的Thread物件
- Thread(String threadname):建立執行緒並指定執行緒例項名
- Thread(Runnable target):指定建立執行緒的目標物件,它實現了Runnable介面中的run方法
- Thread(Runnable target, String name):建立新的Thread物件
-
繼承Thread類的實現步驟
(1)定義子類繼承Thread類。
(2)子類中重寫Thread類中的run方法。
(3)建立Thread子類物件,即建立了執行緒物件。
(4)呼叫執行緒物件start方法:啟動執行緒,呼叫run方法。
public class ThreadTest { public static void main(String[] args) { MyThread myThread = new MyThread(); myThread.start(); // 啟動執行緒 for (int i = 0; i < 300; i++) { if (i % 2 != 0) { System.out.println("main:"+i); } } } } class MyThread extends Thread { @Override public void run() { // 重寫run方法 for (int i = 1; i < 101; i++) { if (i % 2 == 0) { System.out.println(i+" "); } } } }
-
Thread類的有關方法
- void start():啟動執行緒,並執行物件的run()方法 run():執行緒在被排程時執行的操作
- String getName():返回執行緒的名稱
- void setName(String name):設定該執行緒名稱
- static Thread currentThread():返回當前執行緒。在Thread子類中就是this,通常用於主執行緒和Runnable實現類
- static void yield():執行緒讓步
- 暫停當前正在執行的執行緒,把執行機會讓給優先順序相同或更高的執行緒
- 若佇列中沒有同優先順序的執行緒,忽略此方法
- join():當某個程式執行流中呼叫其他執行緒的join()方法時,呼叫執行緒將被阻塞,直到join()方法加入的join執行緒執行完為止
- 低優先順序的執行緒也可以獲得執行
- static void sleep(longmillis):(指定時間:毫秒)
- 令當前活動執行緒在指定時間段內放棄對CPU控制,使其他執行緒有機會被執行,時間到後重排隊
- 丟擲InterruptedException異常
- stop():強制執行緒生命期結束,不推薦使用
- booleanisAlive():返回boolean,判斷執行緒是否還活著
四、執行緒的排程
- cpu的排程策略:
時間片
搶佔式:高優先順序的執行緒搶佔CPU
- Java的排程方法:
- 同優先順序執行緒組成先進先出佇列(先到先服務),使用時間片策略
- 對高優先順序,使用優先排程的搶佔式策略
-
執行緒的優先順序
-
MAX_PRIORITY:10
-
MIN_PRIORITY:1
-
NORM_PRIORITY:5
涉及的方法:
- getPriority():返回執行緒優先值
- setPriority(intnewPriority):改變執行緒的優先順序
說明:
- 執行緒建立時繼承父執行緒的優先順序
- 低優先順序只是獲得排程的概率低,並非一定是在高優先順序執行緒之後才被呼叫
-
五、執行緒的建立方式二 【方式二:實現Runnable介面】
- 定義子類,實現Runnable介面。
- 類中重寫Runnable介面中的run方法。
- 通過Thread類含參構造器建立執行緒物件。
- 將Runnable介面的子類物件作為實際引數傳遞給Thread類的構造器中。
- 呼叫Thread類的start方法:開啟執行緒,呼叫Runnable子類介面的run方法。
public class RunnableTest {
public static void main(String[] args) {
RunTest runTest = new RunTest(); // new 一個例項物件
Thread thread = new Thread(runTest); // 把例項物件傳入Thread的構造器中。
thread.start(); // 開啟執行緒
}
}
class RunTest implements Runnable{ // 實現Runnable介面
@Override
public void run() {
for (int i = 0; i < 101; i++) {
if (i % 2 == 0) {
System.out.println(i);
}
}
}
}
六、比較建立執行緒的兩種方式
-
開發中:優先選擇——實現Runnable介面的方式
-
原因:
- 實現的方式沒有類的單繼承性的侷限性
- 實現的方式更適合來處理多個執行緒有共享資料的情況
- 因為多個執行緒使用的是同一個物件。
- 即不用加static關鍵字,即可處理資料共享。
-
聯絡:
- Thread 類也實現了Runnable介面
- 兩中方式都需要重寫run(),將執行緒的要執行的邏輯宣告在run()中