多線程

目的

為什么在Java中要使用多線程
Java 給多線程編程提供了內(nèi)置的支持。 一條線程指的是進(jìn)程中一個(gè)單一順序的控制流,一個(gè)進(jìn)程中可以并發(fā)多個(gè)線程,每條線程并行執(zhí)行不同的任務(wù)。
多線程是多任務(wù)的一種特別的形式,但多線程使用了更小的資源開銷。
這里定義和線程相關(guān)的另一個(gè)術(shù)語 - 進(jìn)程:一個(gè)進(jìn)程包括由操作系統(tǒng)分配的內(nèi)存空間,包含一個(gè)或多個(gè)線程。一個(gè)線程不能獨(dú)立的存在,它必須是進(jìn)程的一部分。一個(gè)進(jìn)程一直運(yùn)行,直到所有的非守護(hù)線程都結(jié)束運(yùn)行后才能結(jié)束。
多線程能滿足程序員編寫高效率的程序來達(dá)到充分利用 CPU 的目的。
進(jìn)程和線程的區(qū)別
進(jìn)程:每個(gè)進(jìn)程都有獨(dú)立的代碼和數(shù)據(jù)空間(進(jìn)程上下文),進(jìn)程間的切換會(huì)有較大的開銷,一個(gè)進(jìn)程包含1--n個(gè)線程。(進(jìn)程是資源分配的最小單位)
線程:同一類線程共享代碼和數(shù)據(jù)空間,每個(gè)線程有獨(dú)立的運(yùn)行棧和程序計(jì)數(shù)器(PC),線程切換開銷小。(線程是cpu調(diào)度的最小單位)。
多進(jìn)程是指操作系統(tǒng)能同時(shí)運(yùn)行多個(gè)任務(wù)(程序)。
多線程是指在同一程序中有多個(gè)順序流在執(zhí)行。

如何創(chuàng)建一個(gè)線程

我們?nèi)绾卧谝粋€(gè)程序里面創(chuàng)建一個(gè)多線程呢?
我們學(xué)習(xí)了兩種方法來創(chuàng)建一個(gè)線程
一、繼承Thread類創(chuàng)建線程類
下面就是如何使用這個(gè)方法的步驟:
? 定義一個(gè)繼承Thread類的子類,并重寫該類的run()方法;
? 創(chuàng)建Thread子類的實(shí)例,即創(chuàng)建了線程對象;
? 調(diào)用該線程對象的start()方法啟動(dòng)線程。
代碼示例:

class ThreadDemo extends Thread {
    @Override
    public void run(){
        String name=Thread.currentThread().getName();
        for(int i=0;i<100;i++){
            System.out.println(name+":"+(i+1));
            if(this!=MyClass.tt2){
                try{
                    MyClass.tt2.join();
                }
                catch(InterruptedException e){
                    e.printStackTrace();
                }
            }
        }
        super.run();
    }
}
 
public class TestThread {
 
   public static void main(String args[]) {
      ThreadDemo T1 = new ThreadDemo( "Thread-1");
      T1.setName("子線程1");
      T1.start();
      
      ThreadDemo T2 = new ThreadDemo( "Thread-2");
      T2.setName("子線程2");
      T2.start();
   }   
}

二、實(shí)現(xiàn)Runnable接口創(chuàng)建線程類
通過實(shí)現(xiàn)Runnable接口創(chuàng)建線程類的具體步驟
? 定義Runnable接口的實(shí)現(xiàn)類,并重寫該接口的run()方法;
? 創(chuàng)建Runnable實(shí)現(xiàn)類的實(shí)例,并以此實(shí)例作為Thread的target對象,即該Thread對象才是真正的線程對象。

class Demo implements Runnable {
    @Override
    public void run(){
        String name=Thread.currentThread().getName();
        for(int i=0;i<100;i++){
            System.out.println(name+":"+(i+1));
            if(this!=MyClass.tt2){
                try{
                    MyClass.tt2.join();
                }
                catch(InterruptedException e){
                    e.printStackTrace();
                }
            }
        }
        super.run();
    }
}
 
public class TestThread {
 
   public static void main(String args[]) {

      Demo R1 = new Demo();
      Thread onTread2 = new Thread(Demo); 
      onTread1.setName("子線程1");
      onTread1.start();

      Demo R2 = new Demo();     
      Thread onTread2= new Thread(Demo); 
      onTread2.setName("子線程2");
      onTread2.start();
   }   
}

一個(gè)線程的生命周期

線程是一個(gè)動(dòng)態(tài)執(zhí)行的過程,它也有一個(gè)從產(chǎn)生到死亡的過程。
線程和進(jìn)程一樣分為五個(gè)階段:創(chuàng)建、就緒、運(yùn)行、阻塞、終止。
下圖顯示了一個(gè)線程完整的生命周期。

線程的輪回

新建狀態(tài):
使用 new 關(guān)鍵字和 Thread 類或其子類建立一個(gè)線程對象后,該線程對象就處于新建狀態(tài)。它保持這個(gè)狀態(tài)直到程序 start() 這個(gè)線程。
就緒狀態(tài):
當(dāng)線程對象調(diào)用了start()方法之后,該線程就進(jìn)入就緒狀態(tài)。就緒狀態(tài)的線程處于就緒隊(duì)列中,要等待JVM里線程調(diào)度器的調(diào)度。
運(yùn)行狀態(tài):
處于運(yùn)行狀態(tài)的線程最為復(fù)雜,它可以變?yōu)樽枞麪顟B(tài)、就緒狀態(tài)和死亡狀態(tài)。
1、如果就緒狀態(tài)的線程獲取 CPU 資源,就可以執(zhí)行 run(),此時(shí)線程便處于運(yùn)行狀態(tài)。
2、如果該線程失去了cpu資源,就會(huì)又從運(yùn)行狀態(tài)變?yōu)榫途w狀態(tài)。重新等待系統(tǒng)分配資源。也可以對在運(yùn)行狀態(tài)的線程調(diào)用yield()方法,它就會(huì)讓出cpu資源,再次變?yōu)榫途w狀態(tài)。

注: 當(dāng)發(fā)生如下情況是,線程會(huì)從運(yùn)行狀態(tài)變?yōu)樽枞麪顟B(tài):
①、線程調(diào)用sleep方法主動(dòng)放棄所占用的系統(tǒng)資源
②、線程調(diào)用一個(gè)阻塞式IO方法,在該方法返回之前,該線程被阻塞
③、線程試圖獲得一個(gè)同步監(jiān)視器,但更改同步監(jiān)視器正被其他線程所持有
④、線程在等待某個(gè)通知(notify)
⑤、程序調(diào)用了線程的suspend方法將線程掛起。不過該方法容易導(dǎo)致死鎖,所以程序應(yīng)該盡量避免使用該方法。

當(dāng)線程的run()方法執(zhí)行完,或者被強(qiáng)制性地終止,例如出現(xiàn)異常,或者調(diào)用了stop()、desyory()方法等等,就會(huì)從運(yùn)行狀態(tài)轉(zhuǎn)變?yōu)樗劳鰻顟B(tài)。
阻塞狀態(tài):
如果一個(gè)線程執(zhí)行了sleep(睡眠)、suspend(掛起)等方法,失去所占用資源之后,該線程就從運(yùn)行狀態(tài)進(jìn)入阻塞狀態(tài)。在睡眠時(shí)間已到或獲得設(shè)備資源后可以重新進(jìn)入就緒狀態(tài)??梢苑譃槿N:
等待阻塞:運(yùn)行狀態(tài)中的線程執(zhí)行 wait() 方法,使線程進(jìn)入到等待阻塞狀態(tài)。
同步阻塞:線程在獲取 synchronized 同步鎖失敗(因?yàn)橥芥i被其他線程占用)。
其他阻塞:通過調(diào)用線程的 sleep() 或 join() 發(fā)出了 I/O 請求時(shí),線程就會(huì)進(jìn)入到阻塞狀態(tài)。當(dāng)sleep() 狀態(tài)超時(shí),join() 等待線程終止或超時(shí),或者 I/O 處理完畢,線程重新轉(zhuǎn)入就緒狀態(tài)。
死亡狀態(tài):
一個(gè)運(yùn)行狀態(tài)的線程完成任務(wù)或者其他終止條件發(fā)生時(shí),該線程就切換到終止?fàn)顟B(tài)。

Thread類的一些重要方法:

序號 方法描述
1 public void start() 使該線程開始執(zhí)行;Java 虛擬機(jī)調(diào)用該線程的 run 方法。
2 public void run() 如果該線程是使用獨(dú)立的 Runnable 運(yùn)行對象構(gòu)造的,則調(diào)用該 Runnable 對象的 run 方法;否則,該方法不執(zhí)行任何操作并返回。
3 public final void setName(String name) 改變線程名稱,使之與參數(shù) name 相同。
4 public final void setPriority(int priority) 更改線程的優(yōu)先級。
5 public final void setDaemon(boolean on) 將該線程標(biāo)記為守護(hù)線程或用戶線程。
6 public final void join(long millisec) 等待該線程終止的時(shí)間最長為 millis 毫秒。
7 public void interrupt() 中斷線程。
8 public final boolean isAlive() 測試線程是否處于活動(dòng)狀態(tài)。

測試線程是否處于活動(dòng)狀態(tài)。 上述方法是被Thread對象調(diào)用的。下面的方法是Thread類的靜態(tài)方法。

序號 方法描述
1 public static void yield() 暫停當(dāng)前正在執(zhí)行的線程對象,并執(zhí)行其他線程。
2 public static void sleep(long millisec) 在指定的毫秒數(shù)內(nèi)讓當(dāng)前正在執(zhí)行的線程休眠(暫停執(zhí)行),此操作受到系統(tǒng)計(jì)時(shí)器和調(diào)度程序精度和準(zhǔn)確性的影響。
3 public static boolean holdsLock(Object x) 當(dāng)且僅當(dāng)當(dāng)前線程在指定的對象上保持監(jiān)視器鎖時(shí),才返回 true。
4 public static Thread currentThread() 返回對當(dāng)前正在執(zhí)行的線程對象的引用。
5 public static void dumpStack() 將當(dāng)前線程的堆棧跟蹤打印至標(biāo)準(zhǔn)錯(cuò)誤流。

全篇wan

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • ??一個(gè)任務(wù)通常就是一個(gè)程序,每個(gè)運(yùn)行中的程序就是一個(gè)進(jìn)程。當(dāng)一個(gè)程序運(yùn)行時(shí),內(nèi)部可能包含了多個(gè)順序執(zhí)行流,每個(gè)順...
    OmaiMoon閱讀 1,800評論 0 12
  • 又來到了一個(gè)老生常談的問題,應(yīng)用層軟件開發(fā)的程序員要不要了解和深入學(xué)習(xí)操作系統(tǒng)呢? 今天就這個(gè)問題開始,來談?wù)劜?..
    tangsl閱讀 4,310評論 0 23
  • Java多線程學(xué)習(xí) [-] 一擴(kuò)展javalangThread類 二實(shí)現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 3,105評論 1 18
  • 本文主要講了java中多線程的使用方法、線程同步、線程數(shù)據(jù)傳遞、線程狀態(tài)及相應(yīng)的一些線程函數(shù)用法、概述等。 首先講...
    李欣陽閱讀 2,591評論 1 15
  • 林炳文Evankaka原創(chuàng)作品。轉(zhuǎn)載自http://blog.csdn.net/evankaka 本文主要講了ja...
    ccq_inori閱讀 731評論 0 4

友情鏈接更多精彩內(nèi)容