多執行緒
多執行緒的建立方式一
一、建立一個繼承於Thread類的子類
二、重寫Thread類的run()
將此執行緒執行的操作宣告在run()中
三、建立Thread類的子類的物件
4. 通過此物件呼叫start()
- 啟動當前執行緒
- 呼叫當前執行緒的
run()
問題一:我們不能直接呼叫run()
的方式啟動執行緒。(直接呼叫,則是在mian()
主執行緒執行的)
public class ThreadDemo {
public static void main(String[] args) {
//③建立Thread類的子類的物件
MyThread1 m1 = new MyThread1();
MyThread2 m2 = new MyThread2();
//方法一:④通過此物件呼叫start()
m1.start();
m2.start();
//方法二:④建立Thread類的匿名子類的方式
new Thread() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {a
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}.start();
new Thread() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 != 0 ) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}.start();
}
}
//①建立一個繼承於Thread類的子類
class MyThread1 extends Thread {
//②重寫Thread類的run() 將此執行緒執行的操作宣告在run()中
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 == 0 ) {
System.out.println(Thread.currentThread().getName() + ":" +i);
}
}
}
}
//①建立一個繼承於Thread類的子類
class MyThread2 extends Thread {
//②重寫Thread類的run() 將此執行緒執行的操作宣告在run()中
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 != 0 ) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
測試Thread中的常用方法
start()
:啟動當前執行緒,呼叫當前執行緒的run()
方法。
run()
:通常需要重寫Thread
類中的此方法,將建立的執行緒要執行的操作宣告在此方法中。
currentThread()
:靜態方法,返回當前程式碼的執行緒。
getName()
:獲取當前執行緒的名字。
setName()
:設定當前執行緒的名字。
yield()
:釋放當前CPU的執行。
join()
:線上程A中呼叫執行緒B的join()
,此時執行緒A就進入阻塞狀態,直到執行緒B完全執行完之後,執行緒A才結束阻塞狀態。
stop()
:當執行此方法時,強制結束當前執行緒。(已過時)
sleep()
:讓當前執行緒“睡眠”指定的millitime
毫秒,在指定的millitime
毫秒時間內,當前執行緒是阻塞狀態。
isAlive()
:判斷當前執行緒是否存活。
執行緒的優先順序
NORM_PRIORITY = 5;
(預設執行緒級)
MIN_PRIORITY = 1;
MAX_PRIORITY = 10;
如何獲取和設定當前執行緒的優先順序
getPriority()
:獲取當前執行緒的優先順序。
setPriority(int p)
:設定當前執行緒的優先順序。
高優先順序的執行緒要搶佔低優先順序執行緒CPU的執行權,但是隻是從概率上講,高優先順序的執行緒高概率的情況下被執行。並不意味著只有當高優先順序的執行緒執行完以後,才去執行低優先順序。
建立多執行緒方式二(實現Runnable介面)
① 建立一個實現了Runnable
介面的類。
② 實現類去實現Runnable
中的抽象方法:run()
。
③ 建立實現類的物件。
④ 將此物件作為引數傳遞到Thread
類的構造器中,建立Thread
類的物件。
⑤ 通過Thread
類的物件呼叫start()
:
第一步:啟動執行緒。
第二步:呼叫當前執行緒的run()
→呼叫了Runnable
型別的target
的run()
。
//① 建立一個實現了`Runnable`介面的類
class RThread implements Runnable {
//② 實現類去實現`Runnable`中的抽象方法:`run()`
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" +i);
}
}
}
public class ThreadTest1 {
public static void main(String[] args) {
//③ 建立實現類的物件
RThread rThread = new RThread();
//④ 將此物件作為引數傳遞到Thread類的構造器中,建立Thread類的物件
Thread thread1 = new Thread(rThread);
thread1.setName("執行緒一");
//⑤ 通過Thread類的物件呼叫start()
thread1.start();
//再啟動一個執行緒,遍歷100以內的偶數
Thread thread2 = new Thread(rThread);
thread2.setName("執行緒二");
thread2.start();
}
}
比較建立執行緒的兩種方式
開發中:優先選擇,實現Runnable
介面的方式。
原因:
1.繼承的方式有單繼承的侷限性,而實現的方法沒有類的單繼承的侷限性。
2.實現的方法更適合來處理多個執行緒有共享資料的情況。
相同點:兩中方式都需要重寫run()
,將執行緒要執行的邏輯宣告在run()
中。
聯絡:public class Thread implements Runnable{}
,Thread
也是實現Runnable
介面,也重寫了run()
方法。