欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談Java并發(fā)編程中的線程

 更新時(shí)間:2023年08月11日 08:45:23   作者:劉婉晴  
這篇文章主要介紹了淺談Java并發(fā)編程中的線程,操作系統(tǒng)運(yùn)行一個(gè)程序,就會(huì)創(chuàng)建一個(gè)進(jìn)程,在一個(gè)進(jìn)程里可以創(chuàng)建多個(gè)線程,因此線程也叫做輕量級(jí)進(jìn)程,需要的朋友可以參考下

一、線程

線程是操作系統(tǒng)調(diào)度的最小單元,多線程同時(shí)執(zhí)行,可以提高程序性能 。

1. 什么是線程

操作系統(tǒng)運(yùn)行一個(gè)程序,就會(huì)創(chuàng)建一個(gè)進(jìn)程,在一個(gè)進(jìn)程里可以創(chuàng)建多個(gè)線程,因此線程也叫做輕量級(jí)進(jìn)程 。

2. 線程帶來了什么好處

現(xiàn)代處理器都是多核的,程序運(yùn)行過程中能夠創(chuàng)建多個(gè)線程,而一個(gè)線程在一個(gè)時(shí)刻只能運(yùn)行在一個(gè)處理器核心上,如果一個(gè)單線程程序在運(yùn)行時(shí)只能使用一個(gè)處理器核心,那么再多的處理器核心加入也無法顯著提升該程序的執(zhí)行效率。

3. 線程基礎(chǔ)

(1)優(yōu)先級(jí) —— setPriority(int)

線程優(yōu)先級(jí)決定線程需要多或者少分配一些處理器資源的線程屬性

設(shè)置線程優(yōu)先級(jí)時(shí),針對(duì)頻繁阻塞(休眠或者I/O操作)的線程需要設(shè)置較高優(yōu)先級(jí),而偏重計(jì)算(需要較多CPU時(shí)間或者偏運(yùn)算)的線程則設(shè)置較低的優(yōu)先級(jí),確保處理器不會(huì)被獨(dú)占。

程序正確性不能依賴于優(yōu)先級(jí)高低 —— 不同操作系統(tǒng)有不同的處理方式

(2)狀態(tài)

New 初始態(tài)\ Running 運(yùn)行態(tài) \ Blocked 阻塞態(tài) \Waiting 等待態(tài)\ TimeWaiting 超時(shí)等待態(tài)\ Terminated 終止態(tài)

注: Java將操作系統(tǒng)中的運(yùn)行和就緒兩個(gè)狀態(tài)合并稱為運(yùn)行狀態(tài)

阻塞狀態(tài)是線程阻塞在進(jìn)入synchronized關(guān)鍵字修飾的方法或代碼塊(獲取鎖)時(shí)的狀態(tài),但是阻塞在java.concurrent包中Lock接口的線程狀態(tài)卻是等待狀態(tài),因?yàn)閖ava.concurrent包中Lock接口對(duì)于阻塞的實(shí)現(xiàn)均使用了LockSupport類中的相關(guān)方法。

(3)Daemon 線程 —— setDaemon(true)

支持型線程,用作程序中臺(tái)調(diào)度以及支持性工作 當(dāng)一個(gè)Java虛擬機(jī)中不存在非Daemon線程的時(shí)候,Java虛擬機(jī)將會(huì)退出

(4)線程的啟動(dòng)和終止

新構(gòu)造的線程對(duì)象是由其parent線程來進(jìn)行空間分配的,child線程繼承了parent是否為Daemon、優(yōu)先級(jí)和加載資源的contextClassLoader以及可繼承的ThreadLocal,同時(shí)還會(huì)分配一個(gè)唯一的ID來標(biāo)識(shí)這個(gè)child線程,至此,一個(gè)能夠運(yùn)行的線程對(duì)象就初始化好了。

start()方法的含義是:當(dāng)前線程(即parent線程)同步告知Java虛擬機(jī),只要線程規(guī)劃器空閑,應(yīng)立即啟動(dòng)調(diào)用start()方法的線程

(5)中斷

Thread.currentThread().isInterrupted()

  • 中斷可以理解為線程的一個(gè)標(biāo)識(shí)位屬性,它表示一個(gè)運(yùn)行中的線程是否被其他線程進(jìn)行了中斷操作;
  • 中斷狀態(tài)是線程的一個(gè)標(biāo)識(shí)位,中斷操作是一種簡(jiǎn)便的線程間交互方式,這種交互方式適合用來取消或停止任務(wù)
  • 除了中斷以外,還可以利用一個(gè)boolean變量來控制是否需要停止任務(wù)并終止該線程

4. volatile和synchronized關(guān)鍵字

volatile

告知程序任何對(duì)該變量的訪問均需要從共享內(nèi)存中獲取,而對(duì)它的改變必須同步刷新回共享內(nèi)存,它能保證所有線程對(duì)變量訪問的可見性。

synchronized

關(guān)鍵字synchronized可以修飾方法或者以同步塊的形式來進(jìn)行使用,它主要確保多個(gè)線程在同一個(gè)時(shí)刻,只能有一個(gè)線程處于方法或者同步塊中,它保證了線程對(duì)變量訪問的可見性和排他性。

本質(zhì)是對(duì)一個(gè)對(duì)象的監(jiān)視器(monitor)進(jìn)行獲取,而這個(gè)獲取過程是排他的,也就是同一時(shí)刻只能有一個(gè)線程獲取到由synchronized所保護(hù)對(duì)象的監(jiān)視器

任意一個(gè)對(duì)象都擁有自己的監(jiān)視器,當(dāng)這個(gè)對(duì)象由同步塊或者這個(gè)對(duì)象的同步方法調(diào)用時(shí),執(zhí)行方法的線程必須先獲取到該對(duì)象的監(jiān)視器才能進(jìn)入同步塊或者同步方法,而沒有獲取到監(jiān)視器(執(zhí)行該方法)的線程將會(huì)被阻塞在同步塊和同步方法的入口處,進(jìn)入BLOCKED狀態(tài)。

5. 等待通知

等待/通知機(jī)制是指一個(gè)線程A調(diào)用了對(duì)象O的wait()方法進(jìn)入等待狀態(tài),而另一個(gè)線程B調(diào)用了對(duì)象O的notify()或者notifyAll()方法,線程A收到通知后從對(duì)象O的wait()方法返回,進(jìn)而執(zhí)行后續(xù)操作。

等待/通知的相關(guān)方法是任意Java對(duì)象都具備的,因?yàn)檫@些方法被定義在所有對(duì)象的超類java.lang.Object上。

  • 使用wait()、notify()和notifyAll()時(shí)需要先對(duì)調(diào)用對(duì)象加鎖;
  • 調(diào)用wait()方法后,線程狀態(tài)由RUNNING變?yōu)閃AITING,并將當(dāng)前線程放置到對(duì)象的等待隊(duì)列;
  • notify()或notifyAll()方法調(diào)用后,等待線程依舊不會(huì)從wait()返回,需要調(diào)用notify()或notifAll()的線程釋放鎖之后,等待線程才有機(jī)會(huì)從wait()返回;
  • notify()方法將等待隊(duì)列中的一個(gè)等待線程從等待隊(duì)列中移到同步隊(duì)列中,而notifyAll()方法則是將等待隊(duì)列中所有的線程全部移到同步隊(duì)列,被移動(dòng)的線程狀態(tài)由WAITING變?yōu)锽LOCKED;
  • 從wait()方法返回的前提是獲得了調(diào)用對(duì)象的鎖。
synchronized(對(duì)象) {
       while(條件不滿足) {
            對(duì)象.wait();
       }
       對(duì)應(yīng)的處理邏輯
}
synchronized(對(duì)象) {
       改變條件
       對(duì)象.notifyAll();
}

(1)Thread.join()

線程A執(zhí)行了thread.join()語句,其含義是:當(dāng)前線程A等待thread線程終止之后才從thread.join()返回

join() 當(dāng)線程終止時(shí),會(huì)調(diào)用線程自身的notifyAll()方法,會(huì)通知所有等待在該線程對(duì)象上的線程。

(2)ThreadLocal

以ThreadLocal對(duì)象為鍵、任意對(duì)象為值的存儲(chǔ)結(jié)構(gòu),一個(gè)線程可以根據(jù)一個(gè)ThreadLocal對(duì)象查詢到綁定在這個(gè)線程上的一個(gè)值。

ThreadLocal 調(diào)用耗時(shí)統(tǒng)計(jì)的功能上,在方法的入口前執(zhí)行begin()方法,在方法調(diào)用后執(zhí)行end()方法,好處是兩個(gè)方法的調(diào)用不用在一個(gè)方法或者類中,比如在AOP(面向方面編程)中,可以在方法調(diào)用前的切入點(diǎn)執(zhí)行begin()方法,而在方法調(diào)用后的切入點(diǎn)執(zhí)行end()方法,這樣依舊可以獲得方法的執(zhí)行耗時(shí)。

6. 如何實(shí)現(xiàn)等待超時(shí)模式

場(chǎng)景:調(diào)用一個(gè)方法時(shí)等待一段時(shí)間0,如果該方法能夠在給定的時(shí)間段之內(nèi)得到結(jié)果,那么將結(jié)果立刻返回,反之,超時(shí)返回默認(rèn)結(jié)果 。

解決:對(duì)象加鎖 條件循環(huán) 處理邏輯 + 設(shè)置超時(shí)時(shí)間段

應(yīng)用:超時(shí)等待模式可以用來實(shí)現(xiàn) 數(shù)據(jù)庫連接池 中數(shù)據(jù)庫連接操作超時(shí)返回

好處: 保證客戶端線程不會(huì)一直掛在連接獲取的操作上,而是“按時(shí)”返回,并告知客戶端連接獲取出現(xiàn)問題,是系統(tǒng)的一種自我保護(hù)機(jī)制,針對(duì)昂貴資源(比如數(shù)據(jù)庫連接)的獲取都應(yīng)該加以超時(shí)限制。

7. 線程池

為什么需要考慮 C/S 架構(gòu)的程序,如果沒有線程池, 我們客戶端向服務(wù)器發(fā)的請(qǐng)求,每個(gè)請(qǐng)求創(chuàng)建一個(gè)線程,假設(shè)我們有 1 萬個(gè)請(qǐng)求, 那么就需要?jiǎng)?chuàng)建 1 萬的線程進(jìn)行處理。 眾所周知,線程的創(chuàng)建和上下文切換是非常消耗資源的。因此, 需要線程池技術(shù)解決這個(gè)問題 。

線程池好處

  • 消除了頻繁創(chuàng)建和消亡線程的系統(tǒng)資源開銷
  • 面對(duì)過量任務(wù)的提交能夠平緩的劣化

線程池的默認(rèn)實(shí)現(xiàn)

使用一個(gè)線程安全的工作隊(duì)列連接工作者線程和客戶端線程。

線程池種類

newSingleThreadExecutor newFixedThreadPool newCachedThreadPool : 提高執(zhí)行許多短暫的異步任務(wù)的程序的性能

線程池應(yīng)用:

簡(jiǎn)單的 Web 服務(wù)器 常用的Java Web服務(wù)器,如Tomcat、Jetty,在其處理請(qǐng)求的過程中都使用到了線程池技術(shù)。

因?yàn)槲覀儾荒芤粋€(gè)一個(gè)請(qǐng)求的順序處理,這樣的話,估計(jì)就沒有用戶會(huì)想用了 ?,F(xiàn)代的瀏覽器可以并發(fā)發(fā)送多個(gè)請(qǐng)求, 服務(wù)器可以并發(fā)處理多個(gè)請(qǐng)求 。

線程池中線程數(shù)量設(shè)置

線程池中線程數(shù)量并不是越多越好,具體的數(shù)量需要評(píng)估每個(gè)任務(wù)的處理時(shí)間,以及當(dāng)前計(jì)算機(jī)的處理器能力和數(shù)量。使用的線程過少,無法發(fā)揮處理器的性能;使用的線程過多,將會(huì)增加系統(tǒng)的無故開銷,起到相反的作用。

((線程等待時(shí)間+線程CPU時(shí)間)/線程CPU時(shí)間 )* CPU數(shù)目

線程池可能出現(xiàn)的問題

  • 使用默認(rèn)的無界的阻塞隊(duì)列,任務(wù)過多,導(dǎo)致阻塞隊(duì)列炸了 OOM 使用newFixedThreadPool創(chuàng)建的線程池默認(rèn)的是無界的阻塞隊(duì)列,如果任務(wù)過多,會(huì)導(dǎo)致OOM問題。因此,建議自定義線程池,使用指定長(zhǎng)度的阻塞隊(duì)列
  • 線程池創(chuàng)建線程過多,導(dǎo)致JVM無法創(chuàng)建出更多線程,從而導(dǎo)致OOM 使用newCachedThreadPool創(chuàng)建的線程池時(shí),其對(duì)線程數(shù)量沒有規(guī)定,如果某個(gè)業(yè)務(wù)的請(qǐng)求特別多,也會(huì)導(dǎo)致OOM (因?yàn)?newCachedThreadPool 創(chuàng)建的線程沒有規(guī)定數(shù)量,完全由 JVM 能創(chuàng)建的線程數(shù)量而定)
  • 不同業(yè)務(wù)共享線程池,導(dǎo)致次要邏輯拖主要邏輯
  • 線程池拒絕策略 使用不合理的拒絕策略,可能會(huì)導(dǎo)致阻塞問題 。比如使用 DiscardPolicy 或者 DiscardOldestPolicy 策略 并且 被拒絕的任務(wù)調(diào)用 get() 方法,那么調(diào)用線程就會(huì)一直被阻塞 (FutureTask的狀態(tài)大于COMPLETING才會(huì)返回,要不然都會(huì)一直阻塞等待。),這也和 get() 方法本身的問題有關(guān),其不帶超時(shí)時(shí)間,可能會(huì)導(dǎo)致阻塞 。
  • Spring 內(nèi)置線程池 (使用內(nèi)置線程池一定要注意其時(shí)如何創(chuàng)建銷毀線程的)
  • 自定義命名
  • 線程池參數(shù) —— 最佳線程數(shù)量,每個(gè)都要好好配置,做到心中有數(shù)
  • 異常問題 (submit 不會(huì)直接拋出異常, execute 可以 ,最好是try…catch捕獲 )
  • 忘記關(guān)閉

到此這篇關(guān)于淺談Java并發(fā)編程中的線程的文章就介紹到這了,更多相關(guān)Java中的線程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Ubuntu 安裝 JDK8 的兩種方法(總結(jié))

    Ubuntu 安裝 JDK8 的兩種方法(總結(jié))

    下面小編就為大家?guī)硪黄猆buntu 安裝 JDK8 的兩種方法(總結(jié))。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-06-06
  • SpringBoot多種自定義錯(cuò)誤頁面方式小結(jié)

    SpringBoot多種自定義錯(cuò)誤頁面方式小結(jié)

    這篇文章主要介紹了SpringBoot多種自定義錯(cuò)誤頁面方式小結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 深入淺出解析Java ThreadLocal原理

    深入淺出解析Java ThreadLocal原理

    ThreadLocal是JDK包提供的,它提供線程本地變量,如果創(chuàng)建一樂ThreadLocal變量,那么訪問這個(gè)變量的每個(gè)線程都會(huì)有這個(gè)變量的一個(gè)副本,在實(shí)際多線程操作的時(shí)候,操作的是自己本地內(nèi)存中的變量,從而規(guī)避了線程安全問題,感興趣的朋友快來看看吧
    2021-11-11
  • spring boot 命令行啟動(dòng)的方式

    spring boot 命令行啟動(dòng)的方式

    這篇文章主要介紹了spring boot 命令行啟動(dòng)的方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • Spring框架的環(huán)境搭建和測(cè)試實(shí)現(xiàn)

    Spring框架的環(huán)境搭建和測(cè)試實(shí)現(xiàn)

    這篇文章主要介紹了Spring框架的環(huán)境搭建和測(cè)試實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • Java使用mapstruct實(shí)現(xiàn)對(duì)象拷貝

    Java使用mapstruct實(shí)現(xiàn)對(duì)象拷貝

    MapStruct可以簡(jiǎn)化對(duì)象之間的映射,本文就來介紹一下Java使用mapstruct實(shí)現(xiàn)對(duì)象拷貝,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-12-12
  • Mybatis?在?insert?插入操作后返回主鍵?id的操作方法

    Mybatis?在?insert?插入操作后返回主鍵?id的操作方法

    這篇文章主要介紹了Mybatis?在?insert?插入操作后返回主鍵?id的操作方法,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-12-12
  • 詳解Java如何實(shí)現(xiàn)自定義注解

    詳解Java如何實(shí)現(xiàn)自定義注解

    注解(Annotation),也叫元數(shù)據(jù)。一種代碼級(jí)別的說明。它是JDK1.5及以后版本引入的一個(gè)特性,與類、接口、枚舉是在同一個(gè)層次。本文將通過示例詳解Java如何實(shí)現(xiàn)自定義注解,需要的可以參考一下
    2022-06-06
  • 解決SpringBoot中LocalDateTime返回前端數(shù)據(jù)為數(shù)組結(jié)構(gòu)的問題

    解決SpringBoot中LocalDateTime返回前端數(shù)據(jù)為數(shù)組結(jié)構(gòu)的問題

    本文主要介紹了解決SpringBoot中LocalDateTime返回前端數(shù)據(jù)為數(shù)組結(jié)構(gòu)的問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-03-03
  • 解決java調(diào)用dll報(bào)Unable to load library錯(cuò)誤的問題

    解決java調(diào)用dll報(bào)Unable to load library錯(cuò)誤的問題

    這篇文章主要介紹了解決java調(diào)用dll報(bào)Unable to load library錯(cuò)誤的問題。具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11

最新評(píng)論