多線程
線程與進程
- 進程 正在運行的一個程序
系統(tǒng)會為這個進程分配獨立的內存資源 - 線程 具體執(zhí)行任務的最小單位
- 一個進程最少擁有一個線程(主線程 運行起來就執(zhí)行的線程)
- 線程之間是共享內存資源的(進程申請的)
- 線程之間可以通信(數(shù)據(jù)傳遞 多數(shù)為主線程和子線程)
- 每一個線程都有自己的運行回路(生命周期)
-
線程的生命周期 狀態(tài)
線程的生命周期
NEW 新建 線程剛被創(chuàng)建好
RUNNABLE 就緒狀態(tài) 只要搶到時間片就可以運行這個線程
BLOCKED 阻塞狀態(tài) sleep wait
WAITING 等待 wait
TIMED_WAITING
TERMINATED
多線程
為什么需要創(chuàng)建一個子線程?
如果在主線程中存在比較耗時的操作, 這些操作會阻塞主線程, 后面的任務必須等這些任務執(zhí)行完畢之后才執(zhí)行, 用戶體驗差, 為了不阻塞主線程, 需要將耗時的任務放在子線程中執(zhí)行
如何創(chuàng)建一個子線程?
- 協(xié)議類繼承于 Thread 實現(xiàn)run方法
- join 讓當前這個線程阻塞 等join的線程執(zhí)行完畢再執(zhí)行
- setName 設置線程名稱
- getName 獲取線程名稱
- currentThread 獲取當前運行的線程名稱
- start 開啟線程
lass Ticker extends Thread{
private int i;
@Override
public void run() {
for(i=1;i<=100;i++) {
//返回當前線程的名字
System.out.println(getName()+":"+i);
}
}
public static void main(String[] args){
//main方法里面執(zhí)行的代碼 是在主線程里面執(zhí)行的
//(geiName) 主線程的名稱是main
String name = Thread.currentThread().getName();
System.out.println(name);
//創(chuàng)建Thread的對象
Ticker tt1 = new Ticker();
//設置線程的名稱
tt1.setName("子線程1");
//開啟任務
tt1.start();
}
}
- 實現(xiàn)Runnable接口 實現(xiàn)run方法
- 創(chuàng)建任務 創(chuàng)建類實現(xiàn)Runnable接口
- 使用Thread為這個任務分配線程
-
開啟任務 start
Runnable
- 通過 Callable 和 Future 創(chuàng)建線程
- 創(chuàng)建 Callable 接口的實現(xiàn)類晒衩,并實現(xiàn) call() 方法,該 call() 方法將作為線程執(zhí)行體,并且有返回值应狱。
- 創(chuàng)建 Callable 實現(xiàn)類的實例记焊,使用 FutureTask 類來包裝 Callable 對象虏杰,該 FutureTask 對象封裝了該 Callable 對象的 call() 方法的返回值腥刹。
- 使用 FutureTask 對象作為 Thread 對象的 target 創(chuàng)建并啟動新線程脑溢。
- 調用 FutureTask 對象的 get() 方法來獲得子線程執(zhí)行結束后的返回值喻奥。
三種方法對比
- 采用實現(xiàn) Runnable席纽、Callable 接口的方式創(chuàng)建多線程時,線程類只是實現(xiàn)了 Runnable 接口或 Callable 接口撞蚕,還可以繼承其他類润梯。
- 使用繼承 Thread 類的方式創(chuàng)建多線程時,編寫簡單,如果需要訪問當前線程纺铭,則無需使用 Thread.currentThread() 方法寇钉,直接使用 this 即可獲得當前線程。