深入聊聊Java多執行緒

阿豪聊乾貨發表於2017-01-29

一、背景

  在沒有學習Java多執行緒以前,總覺得多執行緒是個很神祕的東西,只有那些大神才能駕馭,新年假期沒事就來學習和了解一下Java的多執行緒,本篇部落格我們就來從頭說一下多執行緒到底是怎麼回事。

二、概述

  1.程式的概念

    每一個正在執行的程式都是一個程式,它是系統進行資源分配和呼叫的獨立單位。且 每一個程式都有自己的記憶體空間和系統資源。

  2.執行緒的概念

    是程式中的單個順序控制流,是一條執行路徑。每個程式都可以擁有一個或者多個執行緒。各個執行緒之間都共享所屬的那個程式的記憶體空間和系統資源。

  3.單執行緒和多執行緒程式的辨別方式

    如果一個程式只有一條執行路徑,則稱為單執行緒程式。 如果一個程式有多條執行路徑,則稱為多執行緒程式(經典應用程式:掃雷、迅雷下載)。

    廢話不多說,我們直接上圖來解釋

    

  4.站線上程的角度來解釋Java程式執行某各類的main方法

    首先java 命令會啟動 java 虛擬機器,即啟動 JVM,等於啟動了一個應用程式,也就是啟動了一個程式。該程式會自動啟動一個 “主執行緒” ,然後主執行緒去呼叫某個類的 main 方法。所以 main方法執行在主執行緒中。在此之前的所有程式都是單執行緒的。

三、多執行緒程式的實現方式

  1.方式一:繼承Thread類,重寫run方法。

 1 package cn.hafiz;
 2 
 3 /*
 4  *多執行緒demo  
 5  */
 6 public class MyThread extends Thread {
 7 
 8     @Override
 9     public void run() {
10         for (int x = 0; x < 200; x++) {
11             System.out.println(x);
12         }
13     }
14 
15 }

  幾個需要注意的問題:

    為什麼要重寫run()方法?

    答:我們只有把想要線上程中執行的程式碼寫在run方法裡才能啟動執行緒進行執行。

    啟動執行緒使用的是那個方法?

    答:啟動使用的是start方法。

    執行緒能不能多次啟動?

    答:一個執行緒只能啟動一次,否則會報IllegalThreadStateException異常。

    run()和start()方法的區別?

    答:run()方法是普通的方法呼叫,並不是啟用執行緒,而start方法是首先啟動一個新的執行緒,然後執行run()方法裡面的程式碼。

  2.方式二:實現Runnable介面

 1 package com.hafiz;
 2 
 3 public class MyRunnable implements Runnable {
 4 
 5     @Override
 6     public void run() {
 7         for (int x = 0; x < 100; x++) {
 8             System.out.println(Thread.currentThread().getName() + ":" + x);
 9         }
10     }
11 
12 }

  該實現方式優點:

    可以避免由於Java單繼承帶來的侷限性。 適合多個相同程式的程式碼去處理同一個資源的情況,

    把執行緒同程式的程式碼,資料有效分離,較好的體現了物件導向的設計思想。

四、執行緒基本操作

  1.獲取和設定執行緒名稱

    public final String getName();

    public final void setName(String name);

    其實通過構造方法也可以設定執行緒名稱.

    public static Thread currentThread():獲取任意方法所在的執行緒名稱.

  2.執行緒排程

    1).之所以出現執行緒排程是因為計算機只有一個 CPU,那麼 CPU 在某一個時刻只能執行一條指令,執行緒只有得到 CPU時間片,也就是使用權,才可以執行指令。

    2).執行緒的兩種排程模型(Java使用的是搶佔式排程模型).

      分時排程模型:所有執行緒輪流使用 CPU 的使用權,平均分配每個執行緒佔用 CPU 的時間片。

      搶佔式排程模型:優先讓優先順序高的執行緒使用 CPU,如果執行緒的優先順序相同,那麼會隨機選擇一個,優先順序高的執行緒獲取的 CPU 時間片相對多一些。

      獲取和設定執行緒優先順序的方法:

        public final int getPriority();

        public final void setPriority(int newPriority);

  3.執行緒控制

    執行緒休眠:public static void sleep(long millis);

    執行緒加入:public final void join();

    執行緒禮讓:public static void yield();

    設定是否為守護執行緒(當所有的執行緒都為守護執行緒就不具有搶佔CPU執行權的資格): 

      public final void setDaemon(boolean on);

    

  上圖中的關羽和張飛可以看成守護執行緒,當劉備主執行緒消亡以後,兩者都不可能再具有獲得CPU執行權的資格。

    中斷執行緒:

      public final void stop();(已過時,直接將虛擬機器退出)

      public void interrupt();(建議使用,是中斷執行緒並且丟擲一個InterruptedException異常,虛擬機器不會退出,執行緒之後的程式碼會繼續執行)

  4.執行緒生命週期

    1).建立:新建執行緒物件。

    2).就緒:執行緒物件已經啟動,已經具有獲得CPU的資格,但沒有獲取執行權。

    3).執行:獲得了CPU的執行權,執行執行緒。

    4).阻塞:沒有CPU的執行權,只能等待會到就緒狀態。

    5).死亡:執行緒程式碼執行完畢,執行緒消亡。

  嫌文字不好理解,直接上圖說明:

  

相關文章