【Java多線程】線程狀態與實現方式

1 參考資料

  1. Java併發編程藝術第4章
  2. https://blog.csdn.net/Alexshi5/article/details/8804576
  3. https://blog.csdn.net/Alex___Zhao/article/details/75137390
  4. https://www.cnblogs.com/yangming1996/p/7612653.html

2 Java中線程的狀態(和OS中線程狀態對比)

首先複習下408中的操作系統的,進程和線程部分吧(唉,回憶起考研時被408支配的恐懼)


進程:計算機中資源分配的基本單位
線程:計算機中任務調度的基本單位

一個進程可以創建多個線程,多個線程共享進程的內存資源,但是,每個線程也有自己的私人空間!


線程的5中狀態:
創建,就緒,運行,阻塞,結束
在這裏插入圖片描述
創建和終止就不用說了,線程中的核心主要是另外3個狀態

Ready: 代表當前的調度實例在可執行隊列中,獲得CPU時間後就可以開始運行

**Running:**Ready獲得了CPU時間後就進入Running狀態,表示正在佔用處理器資源運行。

**Blocked:**代表當前的線程在等待相應的資源,獲得資源後可以轉變爲Ready狀態等待調度


Java中線程的6種狀態,和操作系統中的線程狀態相比,
創建狀態,終止狀態和阻塞狀態是相同的。
不同的是:

  1. 操作系統中的ready和running在Java線程狀態中被統一稱爲了Runnable
  2. Java線程狀態中多了waiting和time_waiting狀態,用於線程之間的通信(這是等待掛起 與之對應的是喚醒 notify)

在這裏插入圖片描述
6個狀態的轉換情況如下圖,
在這裏插入圖片描述

3 Java中線程的實現方式,啓動與終止

啓動

線程如何啓動–start()方法
線程如何結束–run()方法運行結束後,線程也就終止

中斷

中斷可以理解爲線程本身的一個標誌位屬性,其他線程通過調用該線程的interrpt()方法對其進行中斷操作(即 在線程A中,A去調用線程B的 B.interrupt() 方法,則B被中斷

線程檢查自身是否被中斷,調用isInterrupt()方法判斷

如何利用中斷?
我們調用interrupt方法只是改變中斷標誌位,並沒有實際去中斷程序。要想實現中斷操作需要在程序裏手動設置檢查(這就有了很大的靈活性)

終止
  1. 中斷標誌
  2. 新建boolean變量(作用與中斷標誌位類似)
實現

如今實現Java多線程的基本方式有以下幾種

  1. 繼承Thread類
  2. 實現Runnable接口
  3. 實現Callable接口
  4. 使用ExecutorService、Callable、Future實現有返回結果的線程

以下是代碼實現:

package thread;

import java.util.concurrent.*;

public class ThreadTest {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
//        MyThread t = new MyThread("My Thread1");
//        t.start();

//        Thread t2 = new Thread(new MyThread2(),"MyThread2");
//        t2.start();

//        Callable中可以通過範型參數來指定線程的返回值類型。通過FutureTask的get方法拿到線程的返回值。
//        FutureTask<Integer> futureTask = new FutureTask<>(new MyThread3());
//        Thread t3 = new Thread(futureTask,"MyThread3");
//        t3.start();


//        System.out.println("當前線程運行名爲:"+Thread.currentThread().getName());
//        Thread.sleep(1000);
//        System.out.println("當前線程運行名爲:"+Thread.currentThread().getName());
        //System.out.println("MyThread3 的返回值是"+futureTask.get());
        //固定線程池 5
        ExecutorService threadPool = Executors.newFixedThreadPool(5);

        while (true){
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println("當前運行的線程名爲: " + Thread.currentThread().getName());
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            });
        }

    }


}

class MyThread extends Thread{

    public MyThread(){
        super();
    }

    public MyThread(String name){
        super();
        this.setName(name);
    }

    @Override
    public void run() {
        printThreadInfo();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        printThreadInfo();

    }
    public void printThreadInfo(){
        System.out.println("當前線程運行名爲:"+Thread.currentThread().getName());
    }
}

class MyThread2 implements Runnable{
    @Override
    public void run() {
        printThreadInfo();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        printThreadInfo();
    }
    public void printThreadInfo(){
        System.out.println("當前線程運行名爲:"+Thread.currentThread().getName());
    }
}

class MyThread3 implements Callable{
    @Override
    public Object call() throws Exception {
        printThreadInfo();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        printThreadInfo();
        return 1;
    }
    public void printThreadInfo(){
        System.out.println("當前線程運行名爲:"+Thread.currentThread().getName());
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章