1. 程式人生 > >java基礎知多少(三)

java基礎知多少(三)

Java基礎三

定義

百度百科

執行緒 有時被稱為輕量級程序(Lightweight Process,LWP) ,是程式 執行流的最小單元。一個標準的執行緒由執行緒ID,
當前指令指標(PC),暫存器集合和堆疊組成。另外,執行緒是程序中的一個實體,是被系統獨立排程和分派的基本單位,執行緒自己不擁有系統資源,只擁有一點兒在執行中必不可少的資源,但它可與同屬一個程序的其它執行緒共享程序所擁有的全部資源。一個執行緒可以建立和撤消另一個執行緒,同一程序中的多個執行緒之間可以併發執行。由於執行緒之間的相互制約,致使執行緒在執行中呈現出間斷性。執行緒也有就緒、阻塞和執行三種基本狀態。就緒狀態是指執行緒具備執行的所有條件,邏輯上可以執行,在等待處理機;執行狀態是指執行緒佔有處理機正在執行;阻塞狀態是指執行緒在等待一個事件(如某個訊號量),邏輯上不可執行。每一個程式都至少有一個執行緒,若程式只有一個執行緒,那就是程式本身。

執行緒是程式中一個單一的順序控制流程。程序內一個相對獨立的、可排程的執行單元,是系統獨立排程和分派CPU的基本單位指執行中的程式的排程單位。在單個程式中同時執行多個執行緒完成不同的工作,稱為多執行緒。

快速理解

執行緒是程序內的執行單元,不可再分。

基本操作

流程圖

graph LR
  F(TIMED_WAITING) -->|notify通知| B
  B --> |wait等待|F
  A(NEW) --> |start 啟動|B{RUNNABLE}

  B -->|結束|C(TERNINATED)
  B -->|同步塊| D(BLOCKED)
D -->|Synchronized| B B -->|wait等待| E(WAITING) E -->|notify通知| B

程式碼操作

//建立一個執行緒
Thread thread = new Thread();
//啟動一個執行緒
thread.start();

執行緒啟動裡面,有個誤區。不可以直接呼叫run()方法,而是藉助start()方法。

//錯誤的呼叫,不能開啟一個執行緒。
thread.run();

開啟一個執行緒,有兩種方式。
1. 呼叫Thread類例項的start()方法
2. 實現Runna介面,實現run()方法
其實,Thread類run()方法實現的也是Runable介面。

//可以直接過載run()方法來例項化一個Thread類
Thread thread = new Thread(){
    @Override
    public void run(){
        System.out.println("Hello,Thread!");
    }
};
//開啟執行緒
thread.start();

執行緒終止

Thread.stop()

可以直接在程式碼中呼叫stop()方法,來進行終止。不推薦使用這個方式,來終止執行緒,這個方法目前已經被JDK棄用。
因為,一個程式一旦呼叫它,這個執行緒就會在呼叫它的地方強行停止正在做的任務,這就會導致一個執行緒還沒有完成一個完整週期的任務。
類比:戰機正在執行任務,這時接到命令,停止任務的執行,返回基地。如果,呼叫的是stop()方法,戰機直接停止執行任務,但是停止執行任務之後,戰機該做什麼,在這個方法情況下:戰機會直接消失。
示例:有兩個執行緒,讀執行緒R,寫執行緒W,W對臨界區加鎖(Lock),並對變數進行賦值寫入,這是stop(),沒有賦值寫入的欄位會被R讀到,會引發系統不穩定。

中斷

中斷執行緒,推薦使用。

// 中斷執行緒
public void Thread.interrupt()
// 判斷是否被中斷
public boolean Thread.isInterrupted()
// 判斷是否被中斷,並清除當前中斷狀態
public static boolean Thread.interrupted()

寫個小程式碼,實驗一把。
這段程式碼是直接過載執行緒類中的run()方法。可以按照上面寫的程式碼編寫。

@Overrid
public void run(){
    // 無限迴圈
    while(true){
        // 判斷當前執行緒是否被中斷
        if(Thread.currentThread().isInterrupted()){
            System.out.println("Hello Interrupted!");
            break;
        }
        try{
            // 休眠5s ,這裡模仿執行緒做任務
            Thread.sleep(5000);
        }
        // 執行緒會丟擲這個異常,是因為當執行緒休眠是如果有執行緒中斷這個執行緒
        // 就會丟擲這個異常,來中斷休眠並中斷執行緒。
        catch(InterruptedException e){
            System.out.println("Hello InterruptedException.");
            // 清除中斷狀態
            Thread.currentThread().interrupt();
        }
    }
}
掛起和繼續執行

百度百科

掛起 (等待,阻塞)程序在作業系統中可以定義為暫時被淘汰出記憶體的程序,機器的資源是有限的,在資源不足的情況下,作業系統對在記憶體中的程式進行合理的安排,其中有的程序被暫時調離出記憶體,當條件允許的時候,會被作業系統再次調回記憶體,重新進入等待被執行的狀態即就緒態,系統在超過一定的時間沒有任何動作。[
繼續執行,字面意思。掛起是Thread.suspend(),不會釋放鎖。掛起的執行緒直到別的執行緒呼叫此執行緒的resume()方法,此執行緒才會繼續執行。如果執行緒A會呼叫suspend(),執行緒B會呼叫執行緒A的resume(),執行緒B的resume()呼叫發生線上程A的suspend()呼叫之前,就會導致A執行緒所持有的鎖不會被釋放,從而造成死鎖。目前已被JDK棄用。

等待執行緒結束

join()方法,執行緒A生成,起動另一個執行緒B,執行緒B進行大量的耗時的運算,執行緒A將會線上程B之前結束。這不是想要的結果,因為執行緒A處理完其他的事務後,需要用到執行緒B的處理結果,這時候就要用到join()方法,令執行緒A等待執行緒B結束之後,在執行。

// join的本質
while(isAlive()){
    wait(0);
}

例子程式碼

public class ThreadA extend Thread{

    @Override
    public void run(){
        ThreadB threadB = new ThreadB();
        threadB.start();
        //等待執行緒B
        threadB.join();
        //休眠2s
        Thread.sleep(2000s);
    }

    public static class ThreadB{
        @Override
        public void run(){
            //休眠5s
            Thread.sleep(5000s);
        }
    }

}
謙讓(yeild)

當其他執行緒來競爭臨界區,呼叫這個方法的執行緒會主動釋放佔有的CPU,資源釋放,並和其他執行緒一起參與競爭。

守護執行緒

百度百科

守護程序 (Daemon)是執行在後臺的一種特殊程序。它獨立於控制終端並且週期性地執行某種任務或等待處理某些發生的事件。

例子:GC執行緒,JIT執行緒

當JVM中所用執行緒都執行完成後(除了守護執行緒),只剩下守護執行緒時,JVM就會自然退出。

Thread thread = new Thread();
//設定一個執行緒為守護執行緒,要在start()呼叫之前設定,否則會報錯。
thread.setDaemon(true);
thread.start();

優先順序

優先順序越高的執行緒獲得CPU執行權的概率越高。
三個等級
public final static int MIN_PRIORITY = 1;
public final static int NORM_PRIORITY = 5;
public final static int MAX_PRIORITY = 10;

執行緒同步操作

synchronized

百度百科

synchronized 關鍵字,代表這個方法加鎖,相當於不管哪一個執行緒(例如執行緒A),執行到這個方法時,都要檢查有沒有其它執行緒B(或者C、 D等)正在用這個方法(或者該類的其他同步方法),有的話要等正在使用synchronized方法的執行緒B(或者C 、D)執行完這個方法後再執行此執行緒A,沒有的話,鎖定呼叫者,然後直接執行。它包括兩種用法:synchronized 方法和 synchronized 塊。
自定義理解
加鎖,一個房間相當於臨界區,給這個房間加鎖,配一把玥匙,同時只有一個人可以進入。直接作用於例項方法上,相當於對當前例項加鎖,進入同步程式碼前要獲得當前例項的鎖。直接作用於靜態方法上,相當於對當前類加鎖,進入同步程式碼前要獲得當前類的鎖。用於保護共享資料。

例子

@Override
public void run(){
    Object obj = new Object();
    // 把鎖加在例項物件obj上
    synchronized(obj){
        System.out.println("Hello Synchronized.");
    }
}
//作用在普通方法上
public synchronized void method(){
    // do something...
}

//相當於
public void method(){
    synchronized(this){
        //do something...
    }
}
wati() notify()

注意: 這兩個方法是Object類提供的。

舉例說明
兩個執行緒A,B。

執行緒A 執行緒B
取得object監視器 ·
object.wait() ·
釋放object監視器 ·
· 取得object監視器
· object.notify()
等待object監視器 釋放object監視器
重獲object監視器
繼續執行

notify()喚醒一個,notifyAll()喚醒全部在此物件上等待的執行緒

相關推薦

Java基礎——Oracle

通用 唯一標識 系統數據 用戶數 區域 物理 table pac sysdba 一、Oracle內部結構 1.表空間 表空間是數據庫的邏輯劃分,一個表空間只屬於一個數據庫,每個表空間由一個或多個數據文件組成,表空間中其他的邏輯結構的數據存儲在這些數據文件中,一般oracle

Java基礎系列

Iterator和Iterable Iterator: 為了是客戶端用同一種邏輯來遍歷集合,而不用考慮具體是那種集合 對於任意的集合c遍歷其內部的元素都是相同的: for(Iterator it = c.iterator(); it.hasNext(); ) { Object o =

JAVA基礎複習繼承、多型、抽象類和介面

1、超類也稱為父類或者基類,次類又稱為子類或者拓展類、派生類。子類從它的父類中繼承可訪問的資料域和方法,還可以新增新資料域和新方法。 2、繼承:子類並不是父類的一個子集,子類比它的父類包含更多的資訊和方法;父類中的私有資料域在該類之外是不可訪問的;不是所有是一種關係都應該用繼承來建模,但是繼承是

java基礎-中級【異常】

3、異常 3.1 Exception異常的劃分 3.2 檢查性異常和非檢查性異常 3.3 異常的基本方法 3.4 異常的捕獲和丟擲 3.5 finally關鍵字 3.6 自定義異常 3、異常 異常是程式中的一些錯誤,但並不是所有的錯誤都是異

java基礎-初級【類的三大特性詳解】

目錄   3、類的三大特性詳解(封裝、繼承、多型) 3.1 封裝 3.2 繼承       3.2.1 super關鍵字的使用       3.2.2 阻止繼承:final &n

Java基礎鞏固-方法

方法 方法的定義 修飾符 返回值型別 方法名(引數型別 引數名){ ... 方法體 ... return 返回值; } 過載 方法名相同 引數型別或個數不同 返回值相同也可不同 引數 基本資料型別

Java基礎--- 抽象類,介面,final,單目運算子

多型 ①父類引用指向子類: java允許父類的引用變數引用它的子類的例項(物件) Animal animal = new Cat(); 這種轉換是自動完成的 子類在一定條件下是可以轉換為父類的 ②繼承: 類的單繼承和介面的多繼承,都能體現多型 ③重寫、過載 過載:同一個類的同名函式(方法的引

java基礎——異常

前兩次博文介紹了異常的基本概況以及處理異常的方式,這一篇博文介紹自定義異常。 一,自定義異常的定義 通過閱讀異常原始碼:發現java中所有的異常類,都是繼承Throwable,或者繼承Throwable的子類。這樣該異常才可以被throw丟擲。 說明這個異常體系

Java 基礎語法 基本資料型別

Java 的兩大資料型別 內建資料型別 引用資料型別 內建資料型別 Java語言提供了八種基本型別。六種數字型別(四個整數型,兩個浮點型),一種字元型別,還有一種布林型。 byte: byte 資料型別是8位、有符號的,以二進位制補碼錶示的整數; 最

java基礎複習

一、運算子   1.算術運算子     1) 加法(+) 加法   正號  字串拼接     2) 減法(-) 減法 負號     3) 乘法 (*) 乘法     4) 除法(/) 除法

Java基礎總結

首先弄清幾個概念:  1.方法區(method area)只是JVM規範中定義的一個概念,用於儲存類資訊、常量池、靜態變數、JIT編譯後的程式碼等資料,具體放在哪裡,不同的實現可以放在不同的地方。永久代是HotSpot虛擬機器特有的概念,是對方法區的實現,別的JVM沒有永久代的概念。(雖然

Java基礎筆記7----個修飾符

共享 sta strac span 成員 abstract 化工 聲明 訪問修飾符 abstract抽象 方法 抽象方法:abstract修飾的方法,只有聲明 而沒有方法的實現(連{}都沒有)。 語法:修飾符 返回值類型 方法名(形參列表); 註意:抽象方

Java基礎工具1_常用類——用戶和程序交互

size 數據 輸入 方法 main方法 main scanner類 style 輸入數據 2018-05-12 用戶和程序交互 程序接受用戶的輸入數據,有以下三種方式 一、main方法接受參數 二、Console 三、Scanner類 三、Java基

Java基礎工具1_常用類——數學相關類

ref .com 工具 www 小數 spa -- 指數 target 2018-05-13 數學相關類 一、Math類    Java 的 Math 包含了用於執行基本數學運算的屬性和方法,如初等指數、對數、平方根和三角函數。   Math 的方法都被定義為 s

Java基礎工具1_常用類——日期類

for 我們 size CA calendar 大量 col -- bsp 2018-05-14 日期類 一、Date類   講java.util.Date,類 Date 表示特定的瞬間,精確到毫秒。   Date類中大量方法讀已經過時,過時不代表不存在,依然可以

java程式設計師菜鳥進階十五linux基礎入門linux使用者和組管理

我們大家都知道,要登入linux作業系統,我們必須要有一個使用者名稱和密碼。每一個使用者都由一個惟一的身份來標識,這個標識叫做使用者ID.系統中的每一個使用者也至少需要屬於一個"使用者分組".同樣,使用者分組也是由一個惟一的身份來標識的,該標識叫做使用者分組ID(GID).每位使用者的許可

Java基礎系列十九:集合之Collection

Collection是在前文中已經介紹過了,他是兩種集合型別之一的父介面,首先我們來看一下它的框架結構 框架圖 可以看出,作為頂級的框架,Collection僅僅是繼承了Iterable介面,接下來,我們來看一下Iterable的原始碼,看看有什麼收穫。 public

Java基礎系列十八:集合總覽

前言 在我們日常的開發中,集合佔據著舉足輕重的地位。在不同的情況下,我們會去選擇效能更佳(或更安全的)集合類作為一個容器去儲存資料。在接下來的幾節中,我會帶著大家對於集合的知識進行一次系統的深入梳理,相信梳理過後,面試或日常開發再遇到有關集合的問題對我們來說都不會是問題了。 總覽

Java基礎系列十七:泛型繼承,萬用字元,泛型反射

泛型型別的繼承規則 首先,我們來看一個類和它的子類,比如 Fruit 和 Apple。但是Pair<Apple>是Pair<Fruit>的一個子類麼?並不是。比如下面的這段程式碼就會編譯失敗: Apple[] apples = ...; Pair<F

Java基礎系列十六:泛型中需要注意的地方

一、不能用型別引數代替基本型別 因為型別擦除之後,原本的型別會被替代為Object型別的域,而Object不能儲存基本型別的值。就是說沒有Pair<double>,取而代之的是該基本型別的包裝器型別Pair<Double> 二、執行時型別查詢之適用於原始型