多線程3

一、上節(jié)課回顧

????1、多線程的創(chuàng)建和啟動

????????方法一:通過繼承Thread類

????????????classMyThreadextendsThread{

? ????????????????? @Override

? ????????????????? publicvoidrun(){

? ? ? ????????????????????? //此處的代碼,并發(fā)的執(zhí)行。。

????????????????? ? }

????????????????}

????????????publicstaticvoidmain(String[]args){

? ????????????????? MyThreadt1=newMyThread();//創(chuàng)建線程對象

? ????????????????? t1.start();//啟動線程——>準備就緒,就等著被CPU調(diào)度執(zhí)行

????????}

????????方法二:通過實現(xiàn)Runnable接口

????????????????classMyThread2implementsRunnable{

????????????????????????private....//成員變量

????????????????????????????publicvoidrun(){

?????????????????? }

????????????????}

????????????publicstaticvoidmain(String[]args){

????????????????????MyThread2mt=newMyThread2();

????????????????????Threadt2=newThread(mt);

????????????????????Threadt3=newThread(mt);

????????????????????t2.start();

????????????????????t3.start();

????????}

????區(qū)別:

????????1、一種通過繼承的方式,不能再有其他的父類。而通過實現(xiàn)接口,可以再繼承其他的父類。

????????2、通過Runnable接口的方式,可以很方便的實現(xiàn)多個線程之間的數(shù)據(jù)共享。


????2、線程的常用方法:

????????A:線程的Id,線程的唯一標識:long的整數(shù),終身不變。

? ????????????? 由系統(tǒng)自動編號,程序員只能獲取getId(),不能更改

????????B:線程的Name:線程的名稱

? ????????????? 設置和獲取

????????????? ? setName()

????????????? ? getName()

????????????? ? 構造方法:提供名稱

? ? ????????? ? Thread類構造方法:Thread(String name);

????????C:獲取當前的線程對象:靜態(tài)的方法

? ????????????? Thread.currentThread()--->Thread對象

? ? ? ? ? ? ? ? 誰正在被執(zhí)行,就獲取哪個線程對象——>獲取當前的對象

? ? ? ? ? ? ? ? 理解為:該方法在哪個線程中調(diào)用,就是獲取哪個線程對象。

????????D:線程的Priority,優(yōu)先級

????????? ? int整數(shù):

? ? ? ????????????? MAX_PRIORITY:10

? ? ????????????? ? MIN_PRIORITY:1

? ? ? ????????????? NORM_PRIORITY:5

? ? ? ????????? t1,t2,t3..main...-->默認的優(yōu)先級:

????????? ????? setPriority(),getPriority()

????????????? ? 優(yōu)先級高,執(zhí)行的機會多。優(yōu)先級低,執(zhí)行的機會少。


????????E:線程的睡眠:sleep,靜態(tài)的方法

? ????????????????? Thread.sleep(time)

? ????????????????? 當前正在執(zhí)行的線程,進入了睡眠,放棄了CPU的執(zhí)行。和哪個線程對象來調(diào)用無關。

? ? ? ????? 理解為:該方法寫在哪個線程中調(diào)用,就是哪個線程進入睡眠。

????????F:線程的合并:join

????????????????? ? t1,t2,main線程

? ? ? ????????????? main線程中:執(zhí)行了t1.join()

? ????????????? 等待線程死亡——>在main線程中,要等待t1線程結束后,main線程才能執(zhí)行。


????????G:守護線程:daemon

? ????????????????? setDaemon(true)-->設置為守護線程,為前臺線程提供服務,如果所有的前臺線程都結束了,那么守護線程就結束了。

? ????????????????????? isDaemon()-->boolean


3、線程的生命周期

????????線程的生命周期:線程這"一輩子"

????????從創(chuàng)建一個線程對象開始,直到該線程結束,死亡。一個線程只有一輩子,只能被啟動一次。

?

????????新建:線程對象創(chuàng)建出來了

? ????????????? Thread t1 = new Thread();//"剛出生"

????????就緒:執(zhí)行start()方法,萬事準備完畢

? ? ????????????隨時可以被CPU調(diào)度執(zhí)行

????????運行:自動執(zhí)行run()方法

? ??????死亡:線程結束了

????????阻塞:

????????? ????? 暫時不能執(zhí)行:

? ????? 等待:

? ? ? ????????? 有期限:sleep(time)

? ? ? ????????? 無期限:join()

4、多線程之間的共享數(shù)據(jù)安全問題(臨界資源問題)

????????多個線程訪問共享的數(shù)據(jù),可能存在數(shù)據(jù)的不安全。

????????t1線程訪問數(shù)據(jù):中途被其他線程搶跑了,它還修改了。。。t1再搶回來,數(shù)據(jù)已經(jīng)被改了,就是不安全。


5、如何解決臨界資源的問題

????????同步:原子性操作:(化學中表示最小顆粒,不可再分)

????????????計算機中用于表示一次性執(zhí)行完畢。

????????同步:一次性執(zhí)行完畢。

????????語法:關鍵字synchronized

????????????用法一:同步代碼塊:一次只能被一個線程執(zhí)行,中間不允許其他線程插入執(zhí)行的。

????????????????//t1,t2,t3,t4

????????????????synchronized(鎖對象){//開始給對象上鎖,t1

????????????????}//打開對象的鎖

????特征:

????????A:synchronized小括號里的對象,是鎖對象,并要求多線程的情況下,鎖對象必須是同一個對象。

????????B:synchronized大括號里的代碼,就是同步執(zhí)行的代碼。或者說是加了鎖的代碼。意味著每次只能被一個線程執(zhí)行。

????????C:同步的代碼越少越好,在保證安全的情況下,提高性能。

????????D:鎖對象:理論上誰都可以,只要是多個線程訪問的共同對象即可。

? ????????????? this關鍵字,外面創(chuàng)建對象傳入,類名.class,"abc",


????用法二:同步方法:一個方法就是同步,只能被一個線程來執(zhí)行,中間不允許其他線程來打斷執(zhí)行

????????????publicsynchronizedvoidtest(){

????}

????????StringBuffer,StringBuilder,

????同步的原理:對象的"互斥鎖"

????????鎖:打開的狀態(tài)

????????鎖:關閉的狀態(tài)

Java中的任意對象,身上都有互斥鎖。默認就是打開狀態(tài)


多線程同步上鎖鎖不?。?/p>

????多線程存在共享的數(shù)據(jù)安全

????鎖對象,是否是多個線程能夠訪問的共同的對象。99%

????Class類的對象:類編譯后的字節(jié)碼文件對應的對象。

????Object類:

????????對象.getClass()-->Class

????Person:

????????????1.對象.getClass()-->Class

????????????????????p1.getClass()-->Class ---->Person.class

????????? ? 2.類名.class-->Class

????????????????????Person.class

? ? ????????3.Class類中有一個靜態(tài)的方法:forName("類名")

????????????????????Class.forName("com.qf.demo01.Person");-->Class

同步的優(yōu)缺點:

????好處:解決了數(shù)據(jù)安全的問題

????缺點:降低了效率,可能會死鎖

2.1、同步方法

????????同步代碼塊:使用synchronized關鍵字包裹了一塊代碼,讓這塊代碼同步執(zhí)行。就是每次只能一個線程來執(zhí)行。

????????同步方法:使用synchronized關鍵字修飾一個方法,這個方法同步執(zhí)行。就是每次只能一個線程來執(zhí)行。

????????普通的方法:對象調(diào)用。鎖定的對象,就是this對象。

????????靜態(tài)的方法:類調(diào)用。鎖定的對象,就是類名.class

????????同步的原理:利用對象的互斥鎖。

????????????????每個線程來訪問,只能有一個線程進入執(zhí)行,第一個動作鎖對象(上鎖)。來保證其他線程不能進入執(zhí)行。等到該線程結束這個同步代碼塊或者同步方法,釋放鎖對象(開鎖),才允許其他的線程來訪問。

????線程安全的類:

????????????StringBuffer

????????????Vector

????????????HashTable

????????????Collections,集合的工具類


2.2、線程之間的通信

????????線程之間的通信:wait(),notify(),notifyAll()

????????????wait()——>讓線程進入阻塞狀態(tài),暫停執(zhí)行。一直阻塞

????????????notify()——>喚醒線程,wait()住的線程,被喚醒。如果多個線程wait()了,喚醒其中的一個。

????????????notifyAll()——>喚醒所有。

? ??語法要求:必須在同步中,由同步的鎖對象來調(diào)用。否則java.lang.IllegalMonitorStateException異常。


生產(chǎn)者消費者模型:

????????生產(chǎn)者(線程t1)負責生產(chǎn)產(chǎn)品,存入容器中(固定容量),消費者(線程t2)從容器中獲取產(chǎn)品消費掉。

????容器:

? ????? 生產(chǎn)者:持有資源,生產(chǎn)產(chǎn)品,存入容器中

? ????? 消費者:持有資源,消費掉產(chǎn)品。

?

????容器滿了:最多裝8個雞蛋

? ????? 生產(chǎn)者:持有資源,暫停執(zhí)行——直到容器還能繼續(xù)裝。

? ? ?????? 鎖對象.wait()——>會讓線程進入阻塞狀態(tài)。暫停執(zhí)行。notify(),notifyAll()

????? ? 消費者:持有資源,直接消費。。


????容器空了:最少0個。

? ????? 生產(chǎn)者:持有資源,生產(chǎn),存入。。

????? ? 消費者:持有資源,暫停執(zhí)行——直到容器中有產(chǎn)品

? ? ? ? 鎖對象.wait()——>會讓線程進入阻塞狀態(tài)。暫停執(zhí)行。notify(),notifyAll()

????代碼分析:

????????1、產(chǎn)品類:Egg()-->id

????????2、產(chǎn)生者:線程

????????? ????? cpu執(zhí)行,run()-->生產(chǎn)雞蛋,裝入容器

????????3、消費者:線程

????????????? ? cpu執(zhí)行,run()-->從容器中獲取雞蛋,吃掉(打印。。)

????容器對象:

????????????Class實現(xiàn)容器

????????????數(shù)組: Egg[] arr = new Egg[8];

????????????集合:棧,后進先出

? ??????????集合:隊列,先進先出

????同步的代碼:

????????鎖的是容器對象:

wait()和sleep()方法的區(qū)別:

????????出處不同:

????????????????sleep()方法是Thread類中定義的。

????????????????wait()方法是Object類中定義的。

????????解除阻塞的方式不同

????????????????sleep()是時間到,自己醒。

????????????????wait()方法等待被喚醒:notify(),或者是notifyAll()

????????對鎖資源的釋放情況

????????????????sleep(),不釋放,抱著不撒手

????????????????wait(),釋放

三、總結

????同步方法,同步代碼塊

????????????????synchronized(鎖對象){

????????}

????????????????publicsynchronizedvoidtest(){? ? ?

????????}


注意點:

? ? 同步代碼塊:自己指定鎖對象。

? ? 同步方法:鎖對象是固定的。

? ? ? ? 普通的同步方法:鎖對象:this

? ? ? ? 靜態(tài)的同步方法:鎖對象:類名.class

線程之間的通信:生產(chǎn)者消費者模型

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

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

  • 本文主要講了java中多線程的使用方法、線程同步、線程數(shù)據(jù)傳遞、線程狀態(tài)及相應的一些線程函數(shù)用法、概述等。 首先講...
    李欣陽閱讀 2,597評論 1 15
  • Java多線程學習 [-] 一擴展javalangThread類 二實現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 3,108評論 1 18
  • 35. 并行和并發(fā)有什么區(qū)別? 并行是指兩個或者多個事件在同一時刻發(fā)生;而并發(fā)是指兩個或多個事件在同一時間間隔發(fā)生...
    C乖閱讀 362評論 0 0
  • 一擴展javalangThread類二實現(xiàn)javalangRunnable接口三Thread和Runnable的區(qū)...
    和帥_db6a閱讀 593評論 0 1
  • Object類位于java.lang包中,java.lang包有最基礎的和核心的類,在編譯時會自動導入; Obje...
    遇見你的故事閱讀 738評論 0 0

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