一場賽跑引起的并發知識

享學特邀作者:老顧


前言

我們小伙伴們是不是經常需要測試代碼的性能?小伙伴們是不是就會想到jmeter進行壓力測試一下,模擬N個用戶同時執行下,看看響應的時間多少

今天老顧就用一個經典的比賽案例,來嘗試自行編寫個比賽業務,并隨便介紹一下CyclicBarrier和CountDownLatch區別。 可以根據比賽業務,可以抽象出性能測試工具類

需求場景

有N個短跑選手進行比賽,希望記錄下來整個比賽的時間

1、第一名選手跑完比賽路程所花時間
2、最后一名選手跑完比賽路程所花時間
3、所有選手跑完比賽路程所花時間
4、每個選手跑完比賽路程所花時間之和

上面就是業務需求,那我們如何去實現?

分析需求

先上個圖,小伙伴們會更好理解

上圖中4個選手在進行賽跑,我們先看一下賽跑規則:

1、每個選手互不干擾,在自己的賽道上面進行跑步
2、選手在跑步前都需要活動一下,做好預備姿勢
3、選手是應該在裁判一聲槍響下,才能開始跑,不能提前跑
4、每個選手在跑到終點時,裁判會為每個選手記錄成績
5、比賽結束后,大會公布各個選手的成績,以及排名

設計思路

針對上面的規則,我們需要轉換成我們的程序設計:

1、選手間互不干擾,又同時進行賽跑。這個比較簡單,肯定用我們的Thread線程去解決。
2、記錄時間這個也比較簡單,利用System的時鐘

我們先到這邊,先上代碼,創建任務(賽跑)

RunTask代表選手的跑完比賽的耗時,為了真實模擬,加了隨機數,表示每個選手的耗時不一樣。繼續代碼,直接在main方法中,進行比賽

上面是一些基礎變量,記錄耗時。小伙伴要注意要用AtomicLong原子類避免線程安全問題。下面的代碼就是比賽核心邏輯

1、創建線程(選手)
2、執行任務(賽跑)
3、記錄成績(耗時)

大會公布成績

執行比賽

小伙伴看看,是不是明顯不對啊,總耗時盡然為0,肯定有問題。

應該有人發現了,因為我們是在main方法中執行比賽的,其他線程單獨執行,主main線程執行完就終止了程序,而不會管其他線程有沒有結束

這明顯和我們想要的不一樣,我們需要等所有的選手跑完,才能算比賽結束。那應該怎么優化呢?往下看

CyclicBarrier

我們這里引入一個知識點CyclicBarrier循環屏障,CyclicBarrier是一組線程互相等待,只有全部到達屏障點以后才能繼續執行。可以舉個生活場景

大巴車進入服務區進行休息,大巴車是要等到所有乘客上車后,才能發車。并不是一個人上車了就可以發車了。這個是所有乘客都知道的規則,互相等待所有人上車,才發車。循環的意思就是大巴車是一直這種規則,可重復利用

我們比賽的例子正好匹配,不是一個選手到達終點(屏障)就比賽結束,而是要等到所有選手到達終點才能結束比賽

終點優化

根據上面的CyclicBarrier知識點,我們把代碼優化一下

一、增加CyclicBarrier變量

//定義屏障,為什么要加1?
final CyclicBarrier cb = new CyclicBarrier(nThreads + 1);復制代碼

為什么要加1?因為比賽裁判肯定先到終點(即主線程),那也需要等待,所以屏障點需要加1。

注意:這個是根據業務來的,如果設置屏障點,是根據業務邏輯設計的

二、選手跑完到屏障點

在選手跑完后,增加到達屏障點,等待

三、裁判到屏障點

這個代碼是在main主線程的,也就是裁判會先到,設置屏障點

終點優化結束,執行比賽吧

這個成績應該沒有問題,把大賽的成績都正確的顯示出來了。

系統耗時

我們小伙伴再仔細觀察下,上面的成績:

1、最后一名的耗時3397ms

2、比賽執行完耗時3398ms

相差1ms,當然我們這里設計是以毫秒為單位的,如果以納秒為單位他們的相差會比1ms少。這個不是關鍵,關鍵是其實最后一名跑完,其實就是比賽結束了。按照道理比賽執行耗時和最后一名的耗時是一樣的哦。

比賽執行多次,效果都一樣相差1ms。這個是為什么呢?就是因為系統耗時,我們看看比賽是在什么時候記時的,是全部選手開跑后才記時的。這邊就會存在誤差,因為系統執行也會耗時

//上面所有選手都已經開跑了
//整個比賽的開始時間
long startTime = System.currentTimeMillis();
//。。。
//整個比賽的結束時間
long endTime = System.currentTimeMillis();復制代碼

就是因為系統執行也是會消耗時間的。當然耗時不大就是幾納秒。小伙伴知道這個點后,會不會發現我們整個代碼還存在一個問題?

起點問題

我們一場比賽是要等所有選手準備好后,等待裁判發令后,才能開跑。我們來看一下我們的選手開跑代碼

選手是通過for循環創建出來的,而且創新好后,就執行start開跑了。這個是不對的。

小伙伴會說for循環很快的,沒關系吧。

這里是很有關系的,創建選手耗時是比較長的,而且循環體也有耗時。我們看一下之前的系統耗時,就是獲取結束時間也存在系統耗時,何況這里要分配內存、創建對象等。這樣對其他選手就不公平了,那怎么辦?老顧再分享一個并發控制類CountDownLatch

CountDownLatch

CountDownLatch是一個或一組線程等待其他線程完成各自的工作后再執行。舉個例子:

大家考場考試,有人提前交卷,但監考老師是不能走的,因為還有人沒有考完,只有等到所有人交卷了,老師才能走。是不是和CyclicBarrier類似,他們也有不同點,自行百度。

到我們這個案例中,應該要等待所有選手準備好后,才能開跑。

起點優化

增加變量,計數器為1,這個值是由我們的設計決定的

//增加CountDownLatch控制類
final CountDownLatch cdl = new CountDownLatch(1);復制代碼

選手預備等待

裁判發令

裁判發令后,所有的選手就會立即開跑,利用CountDownLatch達到了控制線程等待,一起執行。再執行比賽看看,也解決了系統耗時誤差的問題

-----------大會公布成績-------------
比賽選手數:4
------------------------
所有選手總耗時:6686ms
比賽執行完耗時:1920ms
第一名耗時:1281ms
最后一名耗時:1920ms復制代碼

總結

這篇文章只是個引子,把并發編程的兩個重要的類拋出來,主要介紹應用場景。具體類的用法,小伙伴們可以網上自行學習。還有CyclicBarrier和CountDownLatch兩者有相同點,有些場景可以替換使用。當然他們也有不同點,小伙伴們要注重關注。謝謝!!!

小伙伴是不是會說,那個性能測試工具類呢?其實上面已經把90%的核心代碼介紹了,把跑步抽象成外部傳入的任務,在加入循環執行次數就ok了,小伙伴可以自行完善

END

歡迎長按下圖關注公眾號:享學課堂online!

公眾號后臺回復【java】,獲取精選準備的架構學習資料(視頻+文檔+架構筆記)



轉載于:https://juejin.im/post/5d00ccc9f265da1b8a4f15cc

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/275003.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/275003.shtml
英文地址,請注明出處:http://en.pswp.cn/news/275003.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

oracle中使用子查詢為何取到大于自然數1 rownum 淺度解析

Oracle 沒有提供TOP N 語句,若希望按特定條件查詢前N 條記錄,可以使用偽列ROWNUM。 ROWNUM 是對結果集加的一個偽列,即先查到結果集之后再加上去的一個列(注意:先要 有結果集)。 rownum 的值是oracle 順序分配的從查詢返回的行的編…

巴克萊對沖_“巴克萊的財政預算案”:使金錢管理對心理健康有效—用戶體驗案例研究

巴克萊對沖Disclaimer: all official Barclays assets used for this project are purely for educational/project purposes only and do not reflect the intentions of Barclays or any of its affiliates.免責聲明:用于此項目的所有官方巴克萊資產純粹是出于教育…

6 個對所有 Web 開發者都有用的 GitHub 倉庫

作者:Mehdi Aoussiad原文:https://javascript.plainenglish.io/6-useful-github-repositories-for-all-web-developers-44f26912fd66大家好,我是若川。持續組織了5個月源碼共讀活動,感興趣的可以點此加我微信 ruochuan12 參與&…

快速刪除數據庫中所有表中的數據

今天又學到一招,可以快速刪除數據庫中所有的用戶表中的數據。我是個菜鳥,望各位大神多多指教 select truncate table Name ; from sysobjects where xtypeU order by name asc; 該條語句執行之后會將數據庫中所有的表都查詢出來,復制出來之…

openfiler的iSCSI配置(二)

為什么80%的碼農都做不了架構師?>>> 一.openfiler iSCSI配置 1.啟動iSCSI target server服務。在Services列表下。 2.設置訪問列表。在System---Network Access Configuration下設置。 3.創建卷設備 二.ISCSI客戶端配置 1.安裝open-iscsi # apt-get ins…

送你一份用Electron開發桌面應用的避坑指南【送3本書,含犀牛書】

大家好,我是若川。持續組織了5個月源碼共讀活動,感興趣的可以點此加我微信 ruochuan12 參與,新年第一次送3本書。抽獎規則見文末。如今,Electron 領域發生了重大的變革,Electron 版本更新換代極快,難以計數…

時間續

mois : janvier fvrier mars avril mai juin juillet aot septembre octobre novembre dcembre semaine : lundi mardi mercredi jeudi vendredi samedi dimanche 轉載于:https://www.cnblogs.com/lavieenrose/archive/2012/02/18/2357597.html

nginx修改upstream不重啟的方法(ngx_http_dyups_module模塊)

為什么80%的碼農都做不了架構師?>>> nginx很強大,第三方模塊也不少,淘寶在nginx上很活躍,特別是章亦春,他參與的模塊至少10, 好了今天主角不是他,是一款動態配置upstream的模塊,這個…

c# 設計原則需要學習嗎_向最好的學習:產品設計原則

c# 設計原則需要學習嗎重點 (Top highlight)In my job as Design Team Lead at SimpleSite, I’ve recently been part of creating a set of Product Design Principles. In this process, I spent a lot of time studying the theory, learning about best practices, and ge…

初學Java-接口

在Java語言中,接口有兩種意思: 一是指概念性的接口,即指系統對外提供的所有服務。類的所有能被外部使用者訪問的方法構成了類的接口 二是指用interface關鍵字定義的實實在在的接口,也稱為接口類型。它用于明確的描述系統對外提供的…

Node.js 2021年開發者報告解讀

大家好,我是若川。持續組織了5個月源碼共讀活動,感興趣的可以點此加我微信 ruochuan12 參與,每周大家一起學習200行左右的源碼,共同進步。同時極力推薦訂閱我寫的《學習源碼整體架構系列》 包含20余篇源碼文章。很多人覺得Node.js…

搭建nginx反向代理用做內網域名轉發

為什么80%的碼農都做不了架構師?>>> 情景 由于公司內網有多臺服務器的http服務要映射到公司外網靜態IP,如果用路由的端口映射來做,就只能一臺內網服務器的80端口映射到外網80端口,其他服務器的80端口只能映射到外網的…

外國經典兒童讀物合集pdf_幫助父母在線購買兒童讀物–用戶體驗案例研究

外國經典兒童讀物合集pdfT? As our first group project at GA, we needed to quickly learn how to use several online tools that helped our team of 4 collaborate and communicate while socially distant. Despite the rather extreme circumstances our team was stil…

Windows Azure Marketplace增加對六種語言和HTML5應用程序的支持

對于那些不熟悉Windows Azure Marketplace的人來說,它是一個供數據供應商和開發人員購買和銷售數據集和應用程序的在線市場。 可以在世界上的26個國家使用Windows Azure Marketplace,它現在支持6種語言,包括日語、漢語、法語、德語、西班牙語…

如何優雅處理 async await 錯誤——解讀小而美的 await-to-js 庫

大家好,我是若川。持續組織了5個月源碼共讀活動,感興趣的可以點此加我微信 ruochuan12 參與,每周大家一起學習200行左右的源碼,共同進步。同時極力推薦訂閱我寫的《學習源碼整體架構系列》 包含20余篇源碼文章。這是源碼共讀活動第…

同態加法_同態的Spotify

同態加法重點 (Top highlight)When neumorphism was predicted to be one of the top 2020 UI design trends, I wanted to give it a shot. Having said that, I wanted to explore a type that had not gone overboard, neumorphism in Dark Mode.當neumorphism預計為頂部202…

ubuntu清除無效的右鍵打開方式

為什么80%的碼農都做不了架構師?>>> 今天安裝了幾個程序又將它們刪除了之后發現了一個比較嚴重的后遺癥,在相關文件右鍵打開方式中出現了許多實際已經不存在的文件打開程序名。想了多種方法去除,可是效果不佳,最終采用…

咖啡豆(JavaBean)?香

Sun公司對JavaBean的定義為:可以重復利用的軟件組件,它在遵循JavaBean技術規范的基礎上提供特定的功能,這些功能模塊可以組成更大規模的應用系統。 到底什么是JavaBean? 先看一段代碼: /** * author yong * */ public class Add { public st…

新一代的編譯工具 SWC,97年小哥寫的~

大家好,我是若川。持續組織了5個月源碼共讀活動,感興趣的可以點此加我微信 ruochuan12 參與,每周大家一起學習200行左右的源碼,共同進步。同時極力推薦訂閱我寫的《學習源碼整體架構系列》 包含20余篇源碼文章。最近前端圈掀起了一…

開始學習jQuery和準備工作

<script>$(document).ready(function(){}); 首先&#xff0c;在頁面頂部添加一行script元素&#xff0c;然后在下一行寫上結束符。 瀏覽器會運行script里所有的Javascript&#xff0c;包括jQuery。 在你的script元素里&#xff0c;添加這段代碼&#xff1a;$(document).r…