1. 程式人生 > >java多執行緒Thread

java多執行緒Thread

認識多執行緒,首先要從程式是如何在CPU中進行排程說起,眾所周知,我們自己的筆記本中只有一個CPU,這個CPU在你電腦開機的時候開始就執行著許多程式,比如作業系統,可是一個CPU在某一單位時間只能執行一個程式,而電腦中這麼多的程式CPU是如何安排工作的呢?這就涉及到了併發的概念.
併發:有兩種情況:
- 多個軟體同時執行
- 同一個軟體在同一時刻被多個使用者同時請求

為了滿足併發這一要求,計算機必須對程式和CPU作出調整,以實現併發.
那麼在只有一個核和一塊CPU的前提下計算機是怎麼做的呢?

  • 作業系統將CPU劃分成很多的時間片段
  • 作業系統將程式劃分為程序

    作業系統將一個個程序按照優先順序安排進CPU,當一個程序停止工作的時候,另一個程序立馬上去,使得CPU馬不停蹄的工作,可是這樣還不夠,為了更大程度的提高CPU的利用率,每個程序還被分成了許許多多的執行緒,分的單位越小,CPU被浪費的機會就越少,這樣我們的目的也就到了,即累死CPU.

這兒來正式的介紹一下程序和執行緒的概念:

-程序: process 是一塊包含了某些資源的記憶體區域,作業系統軟體利用程序把軟體程式分割成若干個單元,這個單元就叫程序.
程序在CPU上的上下操作很浪費時間,但是必須存在這種情況,為了能夠讓CPU的利用率更高,給程序再細分為若干執行緒.
實際上在CPU上上下的是執行緒.
- 執行緒

:Thread 程序中所包含的一個或多個執行的單元,稱為執行緒.
程序還擁有一個私有的虛擬記憶體地址空間,該空間僅能被他包含的執行緒訪問.執行緒只能歸屬一個程序,並且他只能訪問該程序的所有資源,
當作業系統建立了一個程序後,該程序就會自動申請一個名為主執行緒或者叫首要執行緒的執行緒.
同類的多個執行緒共享一個塊記憶體空間和一組資源,執行緒本身有一個供程式執行的堆疊,執行緒在切換時負荷小,
因此執行緒被稱之為輕負荷程序,一個程序可以包含多個執行緒

再來聊聊程序和執行緒的區別:

  • 一個程序至少有一個執行緒
  • 執行緒的劃分尺度小於程序,使得多個執行緒併發性高
  • 另外,程序在指定過程中擁有獨立的記憶體單元,而多個執行緒共享程序的記憶體空間,從而極大的提高了程式的執行效率
  • 執行緒在執行過程中與程序區別在於每個獨立的執行緒有一個程式的執行入口,順序執行序列和程式出口
  • 單執行緒不可以獨立執行,由應用程式提供對執行緒的控制 執行緒實際上是一個執行單元(run方法),run不能獨立執行,必須依賴程序

    執行緒的使用場景:

  • 執行緒通常用於在一個應用程式中需要同時完成多個任務的情況,我們可以將每個任務定義一個執行緒,使得他們可以一同工作.

  • 也可以用於在單一執行緒中完成,但是使用多執行緒可以更快的完成所需要的功能.

但我們腦子中有了關於執行緒的知識框架之後就可以進行使用了
執行緒的使用有兩種方法,
方案一:繼承Thread類

  • 此類是執行緒類,其每一個例項物件表示一個可以併發執行的執行緒,我們可以通過繼承此類,並重寫run方法,來定義一個具體的執行緒/
  • run方法中體現的是執行緒的功能,(執行緒的入口和執行緒的出口),啟動執行緒時呼叫執行緒物件的start方法,而不是直接呼叫run方法,

  • start方法將當前執行緒納入執行緒排程,是當前執行緒可以併發執行,當執行緒獲取CPU時間片段之後,開始自動執行run方法中的邏輯
    示例如下:`

public class MyThread1 extends Thread{

    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println("MyThread1.run方法");
    }

}`

(通過main方法進行測試)
注意:執行緒類的測試只能在main方法中執行,不可以在Junit框架下測試

public class Demo {
    public static void main(String[] args) {
        MyThread1 mt1=new MyThread1();
        mt1.run();//可以呼叫run方法,但不是執行緒併發,這是錯誤的呼叫方式
        mt1.start();//把mt1執行緒放到記憶體中,但是不一定呼叫run()
        MyThread1 mt2=new MyThread1();
        mt2.start();
    }
}

方案二:實現Runnable介面

  • :實現此介面並重寫run方法來定義執行緒類,然後在建立執行緒的時候,將runnable介面的例項傳入並啟動執行緒

  • 這樣做的好處可以將執行緒和執行緒要執行的任務分離,減少耦合,同時java是單繼承,定義一個實現Runnable

  • 介面,這樣的做法可以更好地去實現其他介面和繼承父類

/**
 * 方案二:實現自Runnable介面
 * @author 李旭康
 *
 */
public class MyThread1 implements Runnable{

    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println("Runnable MyThread1.run方法");
    }

}

測試類如下:`

public class Demo {
    public static void main(String[] args) {
        MyThread1 mt1=new MyThread1();
        Thread t1=new Thread(mt1);
        t1.start();

        Thread t2=new Thread(mt1);
        t2.start();
    }
}
`

這裡需要注意一下,雖然這兩種方式都可以實現多執行緒的呼叫,但是在實際開發的時候採用的大部分還是方案二,因為方案一是繼承Thread類,繼承是單繼承,而方案二是實現Runnable介面,實現是多實現,採用方案而大大提高了程式的可擴充套件性.

今天主要講解多執行緒的概念,關於多執行緒的具體使用以及常用API將會在下篇文章中做出詳細講解.