1. 程式人生 > >解決多執行緒程式設計中大併發數等待喚醒的問題

解決多執行緒程式設計中大併發數等待喚醒的問題

       在移動交通流調查專案的一個演算法分析程式中,碰到一個業務問題:使用者採集上傳的基站定位資料需要進行分析預處理,方案是先按預定格式解析檔案並從中提取出成百上千個基站定位資料記錄,併合並相同的基站點,根據獲取到的基站位置資訊作為引數,去請求google 基站定位 api,從而得到對應的基站定位經緯度等資訊,接下來再加上華工的演算法分析。

      在執行華工演算法分析邏輯之前,呼叫谷歌api這一步必需全部完成;網路請求是個耗時的過程,故對每一個請求開啟單獨的執行緒(同時請求可能數百個,這裡通過Semaphore訊號量來控制每次發出請求的最大數,該部分的討論不再本話題之類)。

      問題出來了,那麼如何知道所有的網路請求全部完成了,可以進行下一步演算法分析呢?答案是利用前面講的ManualResetEvent來處理;於是有下面的寫法

1 2 3 4 5 //針對每個執行緒 繫結初始化一個ManualResetEvent例項 ManualResetEvent doneEvent = new ManualResetEvent(false); //通過ThreadPool.QueueUserWorkItem(網路請求方法HttpRequest,doneEvent ) 來開啟多執行緒
//將等待事件一一加入事件列表
1 2 3 4 5 6 7 8 9 10 11 12 List<ManualResetEvent> listEvent = new List<ManualResetEvent>(); for(int i=0;i<請求執行緒數;i++){ listEvent.Add(doneEvent); } //主執行緒等待網路請求全部完成 WaitHandle.WaitAll(listEvent.ToArray());
//....接下去的演算法分析 //在網路請求方法HttpRequest的子執行緒中呼叫 doneEvent.Set();//通知主執行緒 本網路請求已經完成

執行好像沒有問題,程式按原定計劃執行;但是當執行緒數大於64個之後丟擲異常

WaitHandles must be less than or equal to 64

原來WaitHandle.WaitAll(listEvent.ToArray()); 這裡listEvent執行緒數不能超過64個

以前解決方法:

下面是吳建飛以前的方案:既然WaitHandle.WaitAll方法只能喚醒64個ManualResetEvent物件,那麼就採用

1 List<List<ManualResetEvent>> _listLocEventList = new List<List<ManualResetEvent>>();

採用這種複雜集合;集合的每個元素也是一個集合(內部每個集合包含最大64個ManualResetEvent物件);和上面一樣 把每個執行緒相關的ManualResetEvent物件新增到該集合;

//主執行緒等待網路請求全部完成

1 2 3 4 foreach (List<ManualResetEvent> listEvent in _listLocEventList) { WaitHandle.WaitAll(listEvent.ToArray()); }

該方案運用起來比較複雜,而且會導致建立大量的ManualResetEvent物件;

現在的設計目標是這種對檔案的分析是多工同時進行的,也就是說會產生的ManualResetEvent物件List<List<ManualResetEvent>>.Size() * 任務數(N個檔案上傳)

改進的解決方法:

原理:封裝一個ManualResetEvent物件,一個計數器current,提供SetOne和WaitAll方法;

主執行緒呼叫WaitAll方法使ManualResetEvent物件等待喚醒訊號;

各個子執行緒呼叫setOne方法 ,setOne每執行一次current減1,直到current等於0時表示所有子執行緒執行完畢 ,呼叫ManualResetEvent的set方法,這時主執行緒可以執行WaitAll之後的步驟。

目標:減少ManualResetEvent物件的大量產生和使用的簡單性。

在這裡我寫了個封裝類:

1 2 3

相關推薦

解決執行程式設計中大併發等待喚醒的問題

       在移動交通流調查專案的一個演算法分析程式中,碰到一個業務問題:使用者採集上傳的基站定位資料需要進行分析預處理,方案是先按預定格式解析檔案並從中提取出成百上千個基站定位資料記錄,併合並相同的基站點,根據獲取到的基站位置資訊作為引數,去請求google 基站

執行之Java中的等待喚醒機制

  多執行緒的問題中的經典問題是生產者和消費者的問題,就是如何讓執行緒有序的進行執行,獲取CPU執行時間片的過程是隨機的,如何能夠讓執行緒有序的進行,Java中提供了等待喚醒機制很好的解決了這個問題!   生產者消費者經典的執行緒中的問題其實是解決執行緒中的通訊問題,就是不同種類的執行緒針對同一資源的操作,

執行四(執行互鎖現象與等待喚醒機制)

       最近在做與下載相關的APK的時候,需要用到多執行緒的一些知識,之前用的不是很多很深入,所以現在重新翻出來學習並且記錄一下,因為學習內容的調整,所以之前的部落格學習計劃有點變動;所以,在這裡先不給出具體的安排了,等這個模組過去之後,再重新更新一下這個系列標題與總介

【小家Java】Future、FutureTask、CompletionService、CompletableFuture解決執行併發中歸集問題的效率對比

相關閱讀 【小家java】java5新特性(簡述十大新特性) 重要一躍 【小家java】java6新特性(簡述十大新特性) 雞肋升級 【小家java】java7新特性(簡述八大新特性) 不溫不火 【小家java】java8新特性(簡述十大新特性) 飽受讚譽 【小家java】java9

Java併發(十八):阻塞佇列BlockingQueue BlockingQueue(阻塞佇列)詳解 二叉堆(一)之 圖文解析 和 C語言的實現 多執行緒程式設計:阻塞、併發佇列的使用總結 Java併發程式設計:阻塞佇列 java阻塞佇列 BlockingQueue(阻塞佇列)詳解

阻塞佇列(BlockingQueue)是一個支援兩個附加操作的佇列。 這兩個附加的操作是:在佇列為空時,獲取元素的執行緒會等待佇列變為非空。當佇列滿時,儲存元素的執行緒會等待佇列可用。 阻塞佇列常用於生產者和消費者的場景,生產者是往佇列裡新增元素的執行緒,消費者是從佇列裡拿元素的執行緒。阻塞佇列就是生產者

網路程式設計併發執行程式設計

多執行緒threading 執行緒與程序的區別可以歸納為以下4點:   1)地址空間和其它資源(如開啟檔案):程序間相互獨立,同一程序的各執行緒間共享。某程序內的執行緒在其它程序不可見。   2)通訊: 程序間通訊 IPC,執行緒間可以直接讀寫程序資料段(如全域性變數)來進行通訊——

Java執行程式設計核心技術(二)物件及變數的併發訪問

最近一直在忙比賽,四五個吧,時間有點緊張,部落格也沒時間更新~ 只能忙裡抽閒 本文屬於Java多執行緒程式設計系列的第二篇,旨在分享我對多執行緒程式設計技術的心得與感悟,順便做下筆記。 如果你閱讀完比較感興趣,歡迎關注我,等待更新後續篇章。 本文主要介紹Java多執行緒中的同步,也就是如何在Java語言中

C++11執行程式設計 第五章: 使用鎖來解決竟態條件

C++11 Multithreading – Part 5: Using mutex to fix Race Conditions Varun February 22, 2015 C++11 Multithreading – Part 5: Using mutex to fi

執行程式設計學習(1)物件及變數的併發訪問

程序:計算機中的程式關於某資料集合上的一次執行活動,是系統進行資源分配和排程的基本單位,是作業系統結構的基礎。 執行緒:在程序中獨立執行的子任務。 在java中以下3種方法可以終止正在執行的執行緒: 1) 使用退出標誌,使執行緒正常退出,也就是當run方法完成後執行緒終

Java併發程式設計(二)執行程式設計

在上一節,我們介紹了程序與執行緒的概念,接下來介紹如何使用多執行緒(暫不介紹多程序)。 2. Thread物件 每個執行緒都對應一個Thread例項,存在兩種策略使用Thread類來建立併發程式。 直接進行執行緒的建立和管理,也就是當需要開啟一個非同

執行程式設計:偽共享以及其解決方案

首先本文是根據多篇部落格的整合而來,依照本人的理解所寫 1.基本概念的瞭解 回到正題,建議先從下面的部落格連結看起以便對下列概念有個基本的瞭解: 1)CPU快取 2)MESI協議以及RFO請求 3)快取行 具體部落格連結:https://www.cnbl

執行與高併發程式設計之基礎知識(上)

前言 幾乎所有的程式設計師都知道,現代作業系統進行資源分配的最小單元是程序,而作業系統進行運算排程的最小單元是執行緒,其實,在Linux中執行緒也可以看作是一種輕量級的程序,那麼執行緒是包含於程序之中的,是程序中實際的運作單位;同一程序中的多個執行緒共用同一塊

執行與高併發程式設計進階(一)

前言: 使用多執行緒的目的: 充分利用CPU資源,提高程式執行速度 使用多執行緒面臨的挑戰: 上下文切換、死鎖、計算機軟硬體資源的限制等問題 結論: 不是一味地開啟執行緒就能夠讓程式最大限度地併發執行,以及提升執行速度,想利用多執行緒提升程式執行速度需要結合實際

【C++執行程式設計學習(1)】-CPU個數、CPU核心數、CPU執行

轉自:CPU個數、CPU核心數、CPU執行緒數(by kimsimple)   CPU個數即CPU晶片個數。 CPU核心數是指物理上,也就是硬體上存在著幾個核心。比如,雙核就是包括2個相對獨立的CPU核心單元組,四核就包含4個相對獨立的CPU核心單元組。 CPU執行緒數是一

【Java執行程式設計核心技術】第二章 物件及變數的併發訪問

synchronized關鍵字 sychronized取得的鎖都是物件鎖,而不是把一段程式碼或方法(函式)當做鎖。 鎖重入功能:當一個執行緒得到一個物件鎖後,再次請求可以再次得到該物件的鎖 出現異常,鎖自動釋放 同步不具有繼承性 class Bas

執行程式設計程式關閉了,但程序還在的解決方案

自己編的一個串列埠程式,從串列埠除錯助手中讀取資料,採用非同步方式,需要用到多執行緒程式設計, 但是每次執行程式,關閉程式時,開啟程序列表,發現程序還在,導致每次串列埠傳送資料過來時,都先要去手動結束程序, 找了很多方法,發現不會用, 下面是一個很簡單的方法,也很管用: 在

C++——執行程式設計(二)std::mutex 執行同步、解決資源競爭問題

前言 執行緒同步 這裡的“同”不是同時、一起執行的意思,而是指協同、協助、互相配合。執行緒同步是指多個執行緒協同步調,按預定的先後次序進行執行。 執行緒A和B一塊配合,A執行到一定程度時要依靠B的某個結果,於是停下來,示意B執行;B依言執行,再將結果給A;

JAVA併發執行程式設計之同步“監視器monitor”(三)

在JAVA虛擬機器中,每個物件(Object和class)通過某種邏輯關聯監視器,為了實現監視器的互斥功能,每個物件(Object和class)都關聯著一個鎖(有時也叫“互斥量”),這個鎖在作業系統書籍中稱為“訊號量”,互斥(“mutex”)是一個二進位制的訊號量。 如果一個執行緒擁有了某些資料的鎖,其他的

解決執行併發問題

1、檔案鎖 如果對該表的更新或插入的操作,都會經過一個統一的檔案,這種方式是可以解決的多程序併發的問題; 實現方式如下: public static function cbInventoryReserve() { $LOCK_FILE_PATH = $_S

18年執行視訊教程併發程式設計網際網路架構視訊java面試知識-張顏源-專題視訊課程...

18年多執行緒視訊教程併發程式設計網際網路架構視訊java面試知識—39人已學習 課程介紹        2018年10月併發程式設計及原理視訊培訓教程:囊括執行緒基礎知識、執行緒安全問題、JDK鎖機制、執行緒建通訊、併發工具、執行緒池等詳細知識點,面試高頻知識點原始碼深入剖