一、背景
在沒有學習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).死亡:線程代碼運行完畢,線程消亡。
嫌文字不好理解,直接上圖說明:

