日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java20-day11【实现多线程(进程、线程-调度-控制-生命周期)、线程同步(同步代码块、线程安全、Lock)、生产者消费者(模式概述、案例)】

發布時間:2024/9/30 java 29 豆豆
  • 視頻+資料【鏈接:https://pan.baidu.com/s/1MdFNUADVSFf-lVw3SJRvtg? ?提取碼:zjxs】
  • Java基礎--學習筆記(零起點打開java世界的大門)--博客匯總表

? ?? ??

目? ?錄

01_進程和線程

1.1、進程

1.2、線程

02_繼承Thread類的方式實現多線程

1.3、多線程的實現方式

03_設置和獲取線程名稱

1.4、設置和獲取線程名稱

04_線程優先級

1.5、線程調度

05_線程控制

1.6、線程控制

06_線程的生命周期

1.7、線程生命周期

07_實現Runnable接口的方式實現多線程

1.8、多線程的實現方式

08_賣票

案例:賣票

09_賣票案例的思考

2.1、賣票案例的思考

10_同步代碼塊解決數據安全問題

2.2、賣票案例數據安全問題的解決

2.3、同步代碼塊

11_同步方法解決數據安全問題

2.4、同步方法

12_線程安全的類

2.5、線程安全的類

13_Lock鎖

2.6、Lock鎖

14_生產者和消費者模式概述

3.1、生產者和消費者模式概述

15_生產者和消費者案例

3.2、生產者和消費者案例


01_進程和線程

1.1、進程

進程:是正在運行的程序。

  • 是系統進行資源分配和調用的獨立單位。
  • 每一個進程都有它自己的內存空間和系統資源。

線程依賴于進程而存在。

在一個進程內部,可以執行一個或多個任務,每個任務可以看成一個線程。

1.2、線程

線程:是進程中的單個順序控制流,是一條執行路徑。

  • 單線程:一個進程如果只有一條執行路徑,則稱為單線程程序。
  • 多線程:一個進程如果有多條執行路徑,則稱為多線程程序。

舉例:

  • 記事本程序
  • 掃雷程序

????掃雷:多線程

02_繼承Thread類的方式實現多線程

1.3、多線程的實現方式

方式1:繼承Thread類

  • 定義一個類MyThread繼承Thread類
  • 在MyThread類中重寫run()方法:MyThread類中可能還有其它的代碼,并不是所有的代碼都要被線程執行。區分可以被線程執行的代碼,Java提供了run()方法,用來封裝被線程執行的代碼。
  • 創建MyThread類的對象
  • 啟動線程

兩個小問題:

  • 為什么要重寫run()方法?

因為run()是用來封裝被線程執行的代碼。

  • run()方法和start()方法的區別?

run():封裝線程執行的代碼,直接調用,相當于普通方法的調用。

start():啟動線程;然后由JVM調用此線程的run()方法。

03_設置和獲取線程名稱

1.4、設置和獲取線程名稱

Thread類中設置和獲取線程名稱的方法:

  • void setName(String name):將此線程的名稱更改為等于參數name。
  • String getName():返回此線程的名稱。
  • 通過構造方法也可以設置線程名稱。

如何獲取main()方法所在的線程名稱?

  • public static Thread currentThread():返回對當前正在執行的線程對象的引用。

Thread部分源碼:

private String name;public Thread() {this(null, null, "Thread-" + nextThreadNum(), 0); }public Thread(String name) {this(null, null, name, 0); }public Thread(ThreadGroup group, Runnable target, String name,long stackSize) {this(group, target, name, stackSize, null, true); }private Thread(ThreadGroup g, Runnable target, String name,long stackSize, AccessControlContext acc,boolean inheritThreadLocals) {this.name = name; }public final synchronized void setName(String name) {this.name = name; }public final String getName() {return name; }private static int threadInitNumber; //0,1,2 private static synchronized int nextThreadNum() {return threadInitNumber++;//0,1,... }

使用帶參構造方法,需要在自己定義的MyThread類中 定義 帶參構造方法,通過super()訪問父類的帶參構造方法:

獲取main()方法 當前正在執行的線程對象的名稱:【名為main的線程】

04_線程優先級

1.5、線程調度

線程調度有兩種調度方式:

  • 分時調度模型:所有線程輪流使用 CPU 的使用權,平均分配每個線程占用 CPU 的時間片。
  • 搶占式調度模型:優先讓優先級高的線程使用CPU,如果線程的優先級相同,那么會隨機選擇一個,優先級高的線程獲取的CPU時間片相對多一些。

Java使用的是搶占式調度模型。

隨機性:

假如計算機只有一個CPU,那么CPU在某一個時刻只能執行一條指令,線程只有得到CPU時間片,也就是使用權,才可以執行指令。所以說多線程程序的執行是有隨機性,因為誰搶到CPU的使用權是不一 定的。

Thread類中設置和獲取線程優先級的方法(優先級相關方法):

  • public final int getPriority():返回此線程的優先級。
  • public final void setPriority(int newPriority):更改此線程的優先級。線程默認優先級是5;線程優先級的范圍是:1-10。

線程默認優先級是5;線程優先級的范圍是:1-10

線程優先級高僅僅表示線程獲取的CPU時間片的幾率高,但是要在次數比較多,或者多次運行的時候才能看到你想要的效果。

05_線程控制

1.6、線程控制

如果有一個線程對象調用了join()方法,其它的線程必須等這個線程執行完畢,其它的線程才有機會執行。

如果主線程執行完畢,剩下的線程全是守護線程的情況下,不會等到守護線程全部執行完,因為Java虛擬機會退出。

sleep()演示:

join()演示:?

setDaemon()演示:

“劉備”線程執行完畢之后,Java虛擬機退出(“關羽”線程、“張飛”線程 停止),需要一定的時間!

06_線程的生命周期

1.7、線程生命周期

線程一共有五種狀態,線程在各種狀態之間轉換。? ?線程生命周期:線程從生到死的過程。

07_實現Runnable接口的方式實現多線程

1.8、多線程的實現方式

方式2:實現Runnable接口:

  • 定義一個類MyRunnable實現Runnable接口
  • 在MyRunnable類中重寫run()方法
  • 創建MyRunnable類的對象
  • 創建Thread類的對象,把MyRunnable對象作為構造方法的參數
  • 啟動線程
  • 多線程的實現方案有兩種:

    • 繼承Thread類
    • 實現Runnable接口

    相比繼承Thread類,實現Runnable接口的好處:

    • 避免了Java單繼承的局限性。
    • 適合多個相同程序的代碼去處理同一個資源的情況,把線程和程序的代碼、數據有效分離,較好的體現了面向對象的設計思想。

    MyRunnable沒有繼承Thread類的好處:MyRunnable將來可以有自己的父類(不影響繼承其它類);可將MyRunnable看成一個資源,由多個線程去使用。

    08_賣票

    ?

    案例:賣票

    ? ??

    09_賣票案例的思考

    2.1、賣票案例的思考

    剛才講解了電影院賣票程序,好像沒有什么問題。但是在實際生活中,售票時出票也是需要時間的,所以,在出售一張票的時候,需要一點時間的延遲,接下來我們去修改賣票程序中賣票的動作:每次出票時間100毫秒,用sleep()方法實現。

    賣票出現了問題

    • 相同的票出現了多次。
    • 出現了負數的票。

    問題產生原因

    • 線程執行的隨機性導致的。

    10_同步代碼塊解決數據安全問題

    2.2、賣票案例數據安全問題的解決

    為什么出現問題?(安全問題出現的條件)(這也是我們判斷多線程程序是否會有數據安全問題的標準)

    • 是否是多線程環境
    • 是否有共享數據
    • 是否有多條語句操作共享數據

    如何解決多線程安全問題呢?

    • 基本思想:讓程序沒有安全問題的環境。

    怎么實現呢?

    • 把多條語句操作共享數據的代碼給鎖起來,讓任意時刻只能有一個線程執行即可。
    • Java提供了同步代碼塊的方式來解決。

    2.3、同步代碼塊

    鎖多條語句操作共享數據,可以使用同步代碼塊實現。

    • 格式:

    synchronized(任意對象) {

    ? ? ? 多條語句操作共享數據的代碼

    }

    • synchronized(任意對象):就相當于給代碼加鎖了,任意對象就可以看成是一把鎖。

    同步的好處和弊端:

    • 好處:解決了多線程的數據安全問題。
    • 弊端:當線程很多時,因為每個線程都會去判斷同步上的鎖,這是很耗費資源的,無形中會降低程序的運行效率。

    (把多條語句操作共享數據的代碼給鎖起來)使用同一把鎖🔒:

    11_同步方法解決數據安全問題

    2.4、同步方法

    同步方法的格式

    同步方法:就是把synchronized關鍵字加到方法上。

    • 格式:

    修飾符 synchronized 返回值類型 方法名(方法參數) { 方法體; }

    同步方法的鎖對象是什么呢?

    • this

    靜態同步方法

    同步靜態方法:就是把synchronized關鍵字加到靜態方法上。

    • 格式:

    修飾符 static synchronized 返回值類型 方法名(方法參數) { 方法體; }

    同步靜態方法的鎖對象是什么呢?

    • 類名.class

    if中的代碼塊與else中的代碼塊,完全一樣!程序不會有問題!

    運行結果同上。

    同步方法:就是把synchronized關鍵字加到方法上。相當于對方法的內部進行鎖定。this代表本類。

    ? ?

    同步方法的鎖對象是什么呢?this

    ? ?

    if代碼塊加鎖,static靜態方法沒有加鎖!--> 報錯!--> 給靜態方法加鎖!

    同步靜態方法:就是把synchronized關鍵字加到靜態方法上。

    if代碼塊中加鎖(this:指代非靜態方法的鎖對象)

    12_線程安全的類

    2.5、線程安全的類

    StringBuffer

    • 線程安全,可變的字符序列。
    • 從版本JDK 5開始,被StringBuilder替代。通常應該使用StringBuilder類,因為它支持所有相同的操作,但它更快,因為它不執行同步。

    Vector

    • 從Java 2平臺v1.2開始,該類改進了List接口,使其成為Java Collections Framework的成員。與新的集合實現不同,Vector被同步。如果不需要線程安全的實現,建議使用ArrayList代替Vector。

    Hashtable

    • 該類實現了一個哈希表,它將鍵映射到值。任何非null對象都可以用作鍵或者值。
    • 從Java 2平臺v1.2開始,該類進行了改進,實現了Map接口,使其成為Java Collections Framework的成員。與新的集合實現不同,Hashtable被同步。如果不需要線程安全的實現,建議使用HashMap代替Hashtable。

    13_Lock鎖

    2.6、Lock鎖

    雖然我們可以理解同步代碼塊和同步方法的鎖對象問題,但是我們并沒有直接看到在哪里加上了鎖,在哪里釋放了鎖,為了更清晰的表達如何加鎖和釋放鎖,JDK5以后提供了一個新的鎖對象Lock。

    Lock實現提供比使用synchronized方法和語句可以獲得更廣泛的鎖定操作。

    Lock中提供了獲得鎖和釋放鎖的方法:

    • void lock() 獲得鎖
    • void unlock() 釋放鎖

    Lock是接口不能直接實例化,這里采用它的實現類ReentrantLock來實例化。

    ReentrantLock的構造方法

    • ReentrantLock():創建一個ReentrantLock的實例

    ?

    ????

    14_生產者和消費者模式概述

    3.1、生產者和消費者模式概述

    15_生產者和消費者案例

    3.2、生產者和消費者案例

    ? ??

    Box.java:

    package com.itheima_12;public class Box {//定義一個成員變量,表示第x瓶奶private int milk;//定義一個成員變量,表示奶箱的狀態private boolean state = false; // 默認沒有牛奶🥛//提供存儲牛奶和獲取牛奶的操作public synchronized void put(int milk) {//如果有牛奶,等待消費if (state) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}//如果沒有牛奶,就生產牛奶this.milk = milk;System.out.println("送奶工將第" + this.milk + "瓶奶放入奶箱");//生產完畢之后,修改奶箱狀態state = true;//喚醒其他等待的線程notifyAll();}public synchronized void get() {//如果沒有牛奶,等待生產if (!state) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}//如果有牛奶,就消費牛奶System.out.println("用戶拿到第" + this.milk + "瓶奶");//消費完畢之后,修改奶箱狀態state = false;//喚醒其他等待的線程notifyAll();} }

    蟹蟹觀看~

    與50位技術專家面對面20年技術見證,附贈技術全景圖

    總結

    以上是生活随笔為你收集整理的Java20-day11【实现多线程(进程、线程-调度-控制-生命周期)、线程同步(同步代码块、线程安全、Lock)、生产者消费者(模式概述、案例)】的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。