文章目錄
- 執行緒概述
- 行程和執行緒
- 執行緒的生命周期
- 執行緒常用方法歸納
- 多執行緒的實作方法
- 案例
- 1. 繼承Thread類,重寫run方法來實作多執行緒
- 2.繼承Runnable介面實作多執行緒
- 繼承Thread類和實作Runnable介面完成多執行緒的區別
- 3. 通過Callable 和 FutureTask創建執行緒
- 4. 通過執行緒池實作多執行緒
- 關于執行緒注意事項
執行緒概述
利用多執行緒技術可以使系統同時運行多個程式塊,縮短出程式回應的時間,提高計算機資源的利用率,達到多任務處理的目的,
行程和執行緒
-
行程是程式的一次動態執行程序,每個行程都有自己獨立的記憶體空間,一個應用程式可以同時啟動多個行程(比如瀏覽器可以開多個視窗,每個視窗就是一個行程)
-
多行程作業系統能夠運行多個行程,每個行程都能夠回圈利用所需要的CPU時間片,使的所有行程看上去像在同時運行一樣,
-
執行緒是行程的一個執行流程,一個行程可以由多個執行緒組成,也就是一個行程可以同時運行多個不同的執行緒,每個執行緒完成不同的任務,
-
執行緒的并發運行:就是一個行程內若干個執行緒同時運行,(比如:word的拼寫檢查功能和首字母自動大寫功能是word行程中的執行緒)
-
執行緒和行程的關系是一個區域和整體的關系,每個行程都由作業系統分配獨立的記憶體地址空間,而同一行程的所有執行緒都在同一地址空間作業,

執行緒的生命周期
一個執行緒的完整生命周期要經歷5中狀態:新建、就緒、運行、阻塞、死亡


- 新建狀態:使用new和某種執行緒的構造方法來創建執行緒物件,該執行緒就會進入新建狀態,系統為該執行緒物件分配記憶體空間,處于新建狀態的執行緒可以通過呼叫**start()**方法進入就緒狀態,
- 就緒狀態:此時執行緒已經具備了運行的條件,進入了執行緒佇列,等待系統分配CPU資源,一旦獲得CPU資源,該執行緒就會進入運行狀態,
- 運行狀態:進入運行在狀態,執行緒會執行自己的**run()**方法中的代碼,
- 阻塞狀態:一個正在執行的執行緒,如果執行了suspend、join或sleep方法,或等待io設備的使用權,那么該執行緒將會讓出自己的CUP控制權并暫時中止自己的執行,進入阻塞狀態,阻塞的執行緒,不能夠進入就緒佇列,只有當阻塞原因被消除的時候,執行緒才能進入就緒狀態,重新進入執行緒佇列中排隊等待CPU資源,然后繼續執行,
- 死亡狀態:一個執行緒完成了全部作業或者被提前強制性的中止,該執行緒就處于死亡狀態,
執行緒常用方法歸納
| 方法名 | 描述 |
|---|---|
| Thread(Runnable target) | 利用Runnable介面子類物件實體化Thread物件 |
| Thread(Runnable target,String name) | 利用Runnable介面子類實體化Tread物件,并指定執行緒名 |
| Thread(String name) | 實體化Thread物件,指定執行緒名 |
| Thread currentThread() | 回傳當前正在執行的執行緒 |
| String getName() | 回傳執行緒名 |
| int getPriority() | 回傳執行緒優先級 |
| boolean isInterrupter() | 判斷執行緒是否中斷,執行緒中斷回傳true,否則回傳false |
| boolean isAlive() | 判斷執行緒是否活動,是回傳true,否則回傳false |
| final void join() | 強制執行緒運行(有些任務需要緊急運行) |
| void run() | 執行執行緒,執行緒執行的主要任務都寫里面 |
| void sleep() | 使正在執行的執行緒暫時休眠(單位 / 毫秒),其他執行緒繼續執行 |
| interrupt() | 強制終端執行緒運行,該執行緒后面的方法不繼續執行 |
| void yield() | 將目前正在執行等的執行緒暫停,運行其他執行緒執行(讓給其他執行緒執行,然后再恢復該執行緒) |
| setName() | 設定執行緒名 |
| setPriority(int new) | 設定執行緒優先級,MIN_PRIORITY(常量值1)最低優先級,NORM_PRIORITY(值5)中等優先級(執行緒的默認優先級),MAX_PRIORITY(值10) 最高優先級 |
| void start() | 啟動執行緒,進入就緒佇列,等待cpu資源就可以進入運行狀態 |
| finalv void setDaemon(boolean on) | 將一個執行緒設定成后臺運行 |
多執行緒的實作方法
案例
1. 繼承Thread類,重寫run方法來實作多執行緒
public class MyThread extends Thread{
private String name;//執行緒名
public MyThread() {
}
public MyThread(String name) {
this.name = name;
}
//完成執行緒功能的主體代碼都在run()方法中
@Override
public void run() {
for (int i = 0; i < 3; i++){
System.out.println(name + "執行功能" + i);
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
//定義執行緒
MyThread thread1 = new MyThread("執行緒A");
MyThread thread2 = new MyThread("執行緒B");
MyThread thread3 = new MyThread("執行緒C");
MyThread thread4 = new MyThread("執行緒D");
MyThread thread5 = new MyThread("執行緒E");
MyThread thread6 = new MyThread("執行緒F");
//呼叫start()方法啟動執行緒,讓其進入就緒狀態,等待系統分配CPU資源進入運行狀態呼叫run()方法
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread5.start();
thread6.start();
}
}
運行結果:(基于4核計算機)
運行三個執行緒(順序執行)

運行6個執行緒(互動執行)

2.繼承Runnable介面實作多執行緒
??重寫run方法,實作Runnable介面的實作類的實體物件作為Thread建構式的target
class MyRunnable implements Runnable {
@Override
public void run() {
for(int i = 0; i < 3; i++){
System.out.println(Thread.currentThread().getName()+"運行功能"+i);
}
}
}
public class RunnableDemo {
public static void main(String[] args) {
//定義執行緒
MyRunnable mt1 = new MyRunnable();
MyRunnable mt2 = new MyRunnable();
MyRunnable mt3 = new MyRunnable();
MyRunnable mt4 = new MyRunnable();
MyRunnable mt5 = new MyRunnable();
MyRunnable mt6 = new MyRunnable();
//利用Runnable介面子類物件來實體化Thread物件
Thread thrad1 = new Thread(mt1,"執行緒1");
Thread thrad2 = new Thread(mt2,"執行緒2");
Thread thrad3 = new Thread(mt3,"執行緒3");
Thread thrad4 = new Thread(mt4,"執行緒4");
Thread thrad5 = new Thread(mt5,"執行緒5");
Thread thrad6 = new Thread(mt6,"執行緒6");
//啟動執行緒
thrad1.start();
thrad2.start();
thrad3.start();
thrad4.start();
thrad5.start();
thrad6.start();
}
}
運行結果:

繼承Thread類和實作Runnable介面完成多執行緒的區別
- 實作Runnable介面可以做到資源共享,而繼承Thread類不行(比如購票問題)
- 實作Runnable介面相比繼承Thread類來說,具有兩大優勢:避免單繼承帶來的局限和可以共享資源等優勢
- 相比Thread類的繼承,一般采用實作Runnable介面來實作多執行緒
3. 通過Callable 和 FutureTask創建執行緒
3.1 創建Callable介面的實作類 ,實作它的Call方法
3.2 使用FutureTask類來包裝Callable物件,這個FutureTask物件需要封裝Callable物件的Call方法的回傳值
3.3 使用FutureTask物件作為Thread物件的target創建并呼叫start方法啟動執行緒
//1. 創建Callable介面的實作類 ,實作它的Call方法
class MyCallable<T> implements Callable<T>{
//重寫Callable的call方法
@Override
public T call() throws Exception {
System.out.println(Thread.currentThread().getName() + " ---->通過實作Callable介面來實作執行緒");
return null;
}
}
public class Callable_FutureTask {
public static void main(String[] args) {
//2. 實體化Callable物件
Callable<Object> callable = new MyCallable<Object>();
//3. 使用FutureTask類來包裝Callable物件
FutureTask<Object> futureTask = new FutureTask<Object>(callable);
//使用FutureTask物件作為Thread物件的target創建并呼叫start方法啟動執行緒
Thread thread1 = new Thread((futureTask),"執行緒A");
System.out.println("當前運行執行緒名:" + Thread.currentThread().getName());
//啟動執行緒
thread1.start();
}
}
運行結果:

4. 通過執行緒池實作多執行緒
class MyRunnable implements Runnable
{
@Override
public void run()
{
System.out.println("通過執行緒池的方式創建的執行緒,執行緒名 :" + Thread.currentThread().getName());
}
}
public class ThreadPool {
//設定執行緒池的數量
private static int threadPoolNum = 8;
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(5);
for(int i = 0; i < threadPoolNum; i ++)
{
//創建執行緒物件
MyRunnable thread = new MyRunnable();
//Thread.sleep(1000);//使執行緒休眠1秒
executorService.execute(thread);
}
}
}
運行結果:

關于執行緒注意事項
- java中,所有執行緒都是同時啟動的,哪個執行緒占有CPU等運行資源,哪個執行緒就可以運行,
- Java程式每次運行都需要啟動兩個執行緒(main執行緒和垃圾收集器執行緒)
- Java執行緒運行程序中,其他執行緒并不會隨著主執行緒的結束而結束,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/67909.html
標籤:其他
上一篇:Redis實作分布式鎖
