深入聊聊Java多線程


一、背景

  在沒有學習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).死亡:線程代碼運行完畢,線程消亡。

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

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM