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

帶你快速搞定java多線程(3)

 更新時(shí)間:2021年07月14日 14:59:26   作者:香菜聊游戲  
這篇文章主要介紹了java多線程編程實(shí)例,分享了幾則多線程的實(shí)例代碼,具有一定參考價(jià)值,加深多線程編程的理解還是很有幫助的,需要的朋友可以參考下

一、鎖的概念

先來聊聊這幾個(gè)概念,總不能聊起來的時(shí)候啥也不知道,只知道干活也沒有用。

公平鎖:當(dāng)線程A獲取訪問該對象,獲取到鎖后,此時(shí)內(nèi)部存在一個(gè)計(jì)數(shù)器num+1,其他線程想訪問該對象,就會(huì)進(jìn)行排隊(duì)等待(等待隊(duì)列最前一個(gè)線程處于待喚醒狀態(tài)),直到線程A釋放鎖(num = 0),此時(shí)會(huì)喚醒處于待喚醒狀態(tài)的線程進(jìn)行獲取鎖的操作,一直循環(huán)。如果線程A再次嘗試獲取該對象鎖時(shí),會(huì)檢查該對象鎖釋放已經(jīng)被占用,如果還是當(dāng)前線程占用鎖,則直接獲得鎖,不用進(jìn)入排隊(duì)。

非公平鎖:當(dāng)線程A在釋放鎖后,等待對象的線程會(huì)進(jìn)行資源競爭,競爭成功的線程將獲取該鎖,其他線程繼續(xù)睡眠。

公平鎖是嚴(yán)格的以FIFO的方式進(jìn)行鎖的競爭,但是非公平鎖是無序的鎖競爭,剛釋放鎖的線程很大程度上能比較快的獲取到鎖,隊(duì)列中的線程只能等待,所以非公平鎖可能會(huì)有“饑餓”的問題。但是重復(fù)的鎖獲取能減小線程之間的切換,而公平鎖則是嚴(yán)格的線程切換,這樣對操作系統(tǒng)的影響是比較大的,所以非公平鎖的吞吐量是大于公平鎖的,這也是為什么JDK將非公平鎖作為默認(rèn)的實(shí)現(xiàn)。

悲觀鎖:總是假設(shè)最壞的情況,每次想要使用數(shù)據(jù)的時(shí)候就恰好別人也要修改數(shù)據(jù),一切是以安全第一,所以在每次操作資源的時(shí)候都會(huì)先加鎖,不管有沒有人搶,然后獨(dú)占資源。Java中synchronized和ReentrantLock等獨(dú)占鎖就是悲觀鎖思想的實(shí)現(xiàn)

樂觀鎖:樂觀鎖和悲觀鎖剛好相反,假定自己使用資源的時(shí)候沒有人搶,所以不需要上鎖。樂觀鎖的實(shí)現(xiàn)方案一般來說有兩種:版本號機(jī)制 和 CAS實(shí)現(xiàn) 。下期可能會(huì)講。

在Java中java.util.concurrent.atomic包下面的原子變量類就是使用了樂觀鎖的一種實(shí)現(xiàn)方式CAS實(shí)現(xiàn)的。

二、synchronized 的使用方式

場景 具體分類 鎖對象 代碼示例
修飾方法 實(shí)例方法 當(dāng)前實(shí)例對象 public synchronized void method () { ... }
... 靜態(tài)方法 當(dāng)前類的Class對象 public static synchronized void method () { ... }
修飾代碼塊 代碼塊 ( )中配置的對象 synchronized(object) { ... }

三、synchronized 的實(shí)現(xiàn)原理列

想知道原來先去底層看下,看看字節(jié)碼是什么樣子的,let's go!

  private static Object lock = new Object();
  public static synchronized void testSyn() {
      System.out.println("香菜");
  }
  public synchronized void testSyn2() {
      System.out.println("香菜");
  }
  public static void testObj() {
      synchronized (lock) {
          System.out.println("香菜");
      }
  }

看下字節(jié)碼:

圖片

可以看到synchronized 的地方使用的是monitorenter指令,每個(gè)對象都和一個(gè)monitor對象關(guān)聯(lián),主要用來控制互斥資源的訪問,如果你想要加鎖必須先獲得monitor的批準(zhǔn),如果現(xiàn)在正有線程訪問,會(huì)把申請的線程加入到等待隊(duì)列。

小結(jié)

1、 無論synchronized關(guān)鍵字加在方法上還是對象上,如果它作用的對象是非靜態(tài)的,則它取得的鎖是對象;如果synchronized作用的對象是一個(gè)靜態(tài)方法或一個(gè)類,則它取得的鎖是對class對象的鎖,該類所有的對象同一把鎖。2、每個(gè)對象只有一個(gè)鎖(lock)與之相關(guān)聯(lián),誰拿到這個(gè)鎖誰就可以運(yùn)行它所控制的那段代碼。

3、實(shí)現(xiàn)同步是要很大的系統(tǒng)開銷作為代價(jià)的,甚至可能造成死鎖,所以盡量避免無謂的同步控制,避免做嵌套synchronized 的使用。

4、synchronized 要盡量控制范圍,不能范圍太大,否則會(huì)損失系統(tǒng)性能。

四、線程池是什么

線程池就是一個(gè)對象持有一堆線程,舉個(gè)例子就是餓了么養(yǎng)的騎手團(tuán)隊(duì)。線程池就是這個(gè)團(tuán)隊(duì),每個(gè)騎手都是一個(gè)線程。

五、為什么要用線程池?

假如現(xiàn)在商家有外賣單子,需要騎手去送單,這個(gè)時(shí)候的外賣任務(wù)就會(huì)派單給騎手,為什么要用線程池吶?

有幾個(gè)好處,第一就是騎手的招聘是有成本的,等你有了外賣訂單再去招聘,來不及了,不如平常養(yǎng)一些騎手,線程的創(chuàng)建和銷毀的開銷是巨大的。

第二就是不能一個(gè)單子來了就來一個(gè)騎手,這樣的話騎手的數(shù)量很難控制,對于派單來說也存在很大的壓力,會(huì)造成整個(gè)騎手團(tuán)隊(duì)的崩潰,對應(yīng)的就是可以通過線程池控制系統(tǒng)內(nèi)的線程數(shù)量,有效的避免大量的線程池爭奪CPU資源而造成堵塞。

第三如果養(yǎng)了一個(gè)騎手團(tuán)隊(duì),這樣在騎手的管理上可以規(guī)范,以便提供更好的外賣服務(wù),比如這種外賣超時(shí),騎手打星等。對比線程池就是線程池可以提供定時(shí)、定期、單線程、并發(fā)數(shù)控制等功能。

六、看下類圖,從整體上理解下

圖片

七、線程池的創(chuàng)建

圖片

線程池主要使用的四種

固定數(shù)量的線程池(FixedThreadPool

定時(shí)線程池(ScheduledThreadPool

可緩存線程池(CachedThreadPool

單線程化線程池(SingleThreadExecutor

八、線程池核心參數(shù)說明

首先看下如何構(gòu)造一個(gè)線程池

  public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
      return new ThreadPoolExecutor(nThreads, nThreads,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>(),
                                    threadFactory);
      public ThreadPoolExecutor(int corePoolSize,
                            int maximumPoolSize,
                            long keepAliveTime,
                            TimeUnit unit,
                            BlockingQueue<Runnable> workQueue,
                            ThreadFactory threadFactory,
                            RejectedExecutionHandler handler)

核心參數(shù)說明:

圖片

九、幾個(gè)疑問點(diǎn)

9.1、是怎么保證線程不銷毀的?

核心線程會(huì)阻塞等待workQueue

9.2 提交任務(wù)有哪幾種方式?

圖片

9.3 拒絕策略都有哪些?

拒絕策略(handler)當(dāng)線程池的線程數(shù)達(dá)到最大線程數(shù)時(shí),需要執(zhí)行拒絕策略。拒絕策略需要實(shí)現(xiàn)RejectedExecutionHandler接口,并實(shí)現(xiàn)rejectedExecution(Runnable r, ThreadPoolExecutor executor)方法。不過Executors框架已經(jīng)為我們實(shí)現(xiàn)了4種拒絕策略:

AbortPolicy(默認(rèn)):丟棄任務(wù)并拋出RejectedExecutionException異常。

CallerRunsPolicy:由調(diào)用線程處理該任務(wù)。

DiscardPolicy:丟棄任務(wù),但是不拋出異常??梢耘浜线@種模式進(jìn)行自定義的處理方式。

DiscardOldestPolicy:丟棄隊(duì)列最早的未處理任務(wù),然后重新嘗試執(zhí)行任務(wù)。

9.4 線程池的關(guān)閉

關(guān)閉線程池可以調(diào)用shutdownNow和shutdown兩個(gè)方法來實(shí)現(xiàn)

shutdownNow:對正在執(zhí)行的任務(wù)全部發(fā)出interrupt(),停止執(zhí)行,對還未開始執(zhí)行的任務(wù)全部取消,并且返回還沒開始的任務(wù)列表。

shutdown:當(dāng)我們調(diào)用shutdown后,線程池將不再接受新的任務(wù),但也不會(huì)去強(qiáng)制終止已經(jīng)提交或者正在執(zhí)行中的任務(wù)。

9.5 初始化線程池時(shí)線程數(shù)的選擇

如果任務(wù)是IO密集型,一般線程數(shù)需要設(shè)置2倍CPU數(shù)以上,以此來盡量利用CPU資源。

如果任務(wù)是CPU密集型,一般線程數(shù)量只需要設(shè)置CPU數(shù)加1即可,更多的線程數(shù)也只能增加上下文切換,不能增加CPU利用率。

具體問題具體分析。

十、總結(jié)

線程池是項(xiàng)目中常用的,需要理解線程池的應(yīng)用場景和構(gòu)造函數(shù),正確的使用線程池。

本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • Java字符串常量池示例詳解

    Java字符串常量池示例詳解

    作為最基礎(chǔ)的引用數(shù)據(jù)類型,Java設(shè)計(jì)者為 String 提供了字符串常量池以提高其性能,下面這篇文章主要給大家介紹了關(guān)于Java字符串常量池的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • @Configuration保證@Bean單例語義方法介紹

    @Configuration保證@Bean單例語義方法介紹

    這篇文章主要介紹了SpringBoot中的@Configuration與@Bean注解,在進(jìn)行項(xiàng)目編寫前,我們還需要知道一個(gè)東西,就是SpringBoot對我們的SpringMVC還做了哪些配置,包括如何擴(kuò)展,如何定制,只有把這些都搞清楚了,我們在之后使用才會(huì)更加得心應(yīng)手
    2023-01-01
  • java組件smartupload實(shí)現(xiàn)上傳文件功能

    java組件smartupload實(shí)現(xiàn)上傳文件功能

    這篇文章主要為大家詳細(xì)介紹了java組件smartupload實(shí)現(xiàn)上傳文件功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • SpringBoot 策略模式實(shí)現(xiàn)切換上傳文件模式

    SpringBoot 策略模式實(shí)現(xiàn)切換上傳文件模式

    策略模式是指有一定行動(dòng)內(nèi)容的相對穩(wěn)定的策略名稱,這篇文章主要介紹了SpringBoot 策略模式 切換上傳文件模式,需要的朋友可以參考下
    2023-11-11
  • java 相交鏈表的實(shí)現(xiàn)示例

    java 相交鏈表的實(shí)現(xiàn)示例

    本文主要介紹了java 相交鏈表的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • java 終止線程的4種方式小結(jié)

    java 終止線程的4種方式小結(jié)

    本文主要介紹了java終止線程的4種方式小結(jié),包含布爾標(biāo)志位,interrupt()方法,stop()方法和Thread.interrupt()方法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-05-05
  • 微服務(wù)Spring Boot 整合 Redis 實(shí)現(xiàn)UV 數(shù)據(jù)統(tǒng)計(jì)的詳細(xì)過程

    微服務(wù)Spring Boot 整合 Redis 實(shí)現(xiàn)UV 數(shù)據(jù)統(tǒng)計(jì)的詳

    這篇文章主要介紹了微服務(wù)Spring Boot 整合 Redis 實(shí)現(xiàn) UV 數(shù)據(jù)統(tǒng)計(jì),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-01-01
  • Java中BigDecimal類的使用詳解

    Java中BigDecimal類的使用詳解

    這篇文章主要介紹了Java中BigDecimal類的使用詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • Java中的snowflake算法詳解

    Java中的snowflake算法詳解

    這篇文章主要介紹了Java中的snowflake算法詳解,Snowflake算法產(chǎn)生是為了滿足Twitter每秒上萬條消息的請求,每條消息都必須分配一條唯一的id,這些id還需要一些大致的順序,并且在分布式系統(tǒng)中不同機(jī)器產(chǎn)生的id必須不同,需要的朋友可以參考下
    2023-08-08
  • 深入理解Java編程中異常處理的優(yōu)劣

    深入理解Java編程中異常處理的優(yōu)劣

    本篇文章是對Java編程中異常處理的優(yōu)劣進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05

最新評論