作者:季沐測試筆記
原文地址:https://www.cnblogs.com/testero/p/15130935.html
博客主頁:https://www.cnblogs.com/testero
1 進程和線程
1.1 進程:正在運行的程序
是系統進行資源分配和調用的獨立單位
每一個進程都有它自己的內存空間和系統資源
1.2 線程是進程中的單個順序控制流,是一條執行路徑
單線程 即一個控制流,多線程即多個控制流
2 多線程的實現
2.1 繼承Thread實現:
-
方法介紹
方法名 說明 void run() 在線程開啟后,此方法將被調用執行 void start() 使此線程開始執行,Java虛擬機會調用run方法() -
實現步驟
- 定義一個類繼承Thread類
- 在類中重寫run()方法
- 創建類的對象
- 啟動線程
-
代碼示例
public class ThreadDemo extends Thread{
@Override
public void run() {
for (int i = 1;i < 20;i++){
System.out.println(getName()+":"+i);
}
}
public static void main(String[] args) {
ThreadDemo threadDemo1 = new ThreadDemo();
ThreadDemo threadDemo2 = new ThreadDemo();
threadDemo1.setName("線程1");
threadDemo2.setName("線程2");
System.out.println(threadDemo1.getPriority());
System.out.println(threadDemo2.getPriority());
threadDemo2.setPriority(6);
threadDemo1.start();
threadDemo2.start();
System.out.println(Thread.currentThread().getName());
}
}
2.1.1 注意:
- run方法封裝線程執行的代碼,直接調用,相當於普通的方法
- start啟動線程,然后由JVM調用此線程的run方法
2.1.2 獲取和設置線程名稱
-
方法介紹
方法名 說明 void setName(String name) 將此線程的名稱更改為等於參數name String getName() 返回此線程的名稱 Thread currentThread() 返回對當前正在執行的線程對象的引用
2.1.3 線程調度模型
-
模型分類
1、分時調度 所有線程輪流使用CPU的使用權,平均分配每個線程占用CPU的時間片
2、搶占調度 優先讓優先級高的線程使用CPU,如果線程的優先級相同會隨機選擇一個 -
Thread()類中獲取和設置優先級的方法
- 獲取優先級public final int getPriority()
- 設置優先級public final void setPriority(int newPriority)
- Thread.MIN_PRIORITY 值為1
- Thread.MAX_PRIORITY 值為10
- ThreadDemo.NORM_PRIORITY 值為 5
- 線程優先級高僅僅表示獲取CPU時間片的幾率高,並不是每次都會優先執行
2.1.4 線程的生命周期
線程一共有五種狀態,線程在各種狀態之間轉換。
2.2 實現Runnable:
-
Thread構造方法
方法名 說明 Thread(Runnable target) 分配一個新的Thread對象 Thread(Runnable target, String name) 分配一個新的Thread對象 -
實現步驟
- 定義一個類MyRunnable實現Runnable接口
- 在MyRunnable類中重寫run()方法
- 創建MyRunnable類的對象
- 創建Thread類的對象,把MyRunnable對象作為構造方法的參數
- 啟動線程
-
代碼示例
public class RunnableDemo implements Runnable {
@Override
public void run() {
for (int i = 1;i < 100;i++){
System.out.println(i);
}
}
public static void main(String[] args) {
RunnableDemo runnableDemo = new RunnableDemo();
Thread thread1 = new Thread(runnableDemo,"線程1");
Thread thread2 = new Thread(runnableDemo,"線程2");
thread1.start();
thread2.start();
}
}
與Thread相比,實現Runnable的好處:
- 避免了Java單繼承的局限性
- 適合多個相同程序的代碼處理同一個資源的情況,把線程和程序的代碼、數據有效分離,較好的體現了面向對象的思維
3、實現 Callable接口(Callable接口有返回值 Runnable接口無返回值),使用ExecutorService、Callable、Future實現有返回結果的多線程
- 示例代碼
public class CallableDemo implements Callable {
//1)重寫抽象方法call方法
@Override
public Integer call() throws Exception {
int result = new Random().nextInt(100);
System.out.println("執行子線程完成某次計算,結果為"+result);
return result;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
//2)創建Callable接口實現類對象
CallableDemo callableDemo = new CallableDemo();
//FutureTask實現了RunnableFuture接口,RunnableFuture繼承了Runnable接口,FutureTask接口就是Runnable接口的實現類
FutureTask<Integer> task = new FutureTask<>(callableDemo);
Thread thread1 = new Thread(task); //線程池:省去了創建線程、釋放線程的時間
//3)開啟新的線程
thread1.start();
System.out.println("result="+task.get());
}
}