并发编程-01并发初窥
文章目錄
- 引言
- 思維導圖
- 基礎知識構建
- 涉及的知識點一覽
- 高并發處理思路與手段一覽
- 并發初窺
- 概念
- 并發問題模擬
- 代碼
引言
說來慚愧,一直沒有系統的梳理過并發編程的知識,這次借著學習_Jimin_老師的《Java并發編程與高并發解決方案》課程的機會,結合以往工作中的使用,好好的梳理下并發編程與高并發的知識,形成一個較為完善的并發編程知識體系。
思維導圖
基礎知識構建
涉及的知識點一覽
高并發處理思路與手段一覽
并發初窺
概念
并發: 同時擁有兩個或者多個線程,如果程序在單核處理器上運行多個線程將交替地換入或者換出內存,這些線程是 同時“存在”的,每個線程都處于執行過程中的某個狀態,如果運行在多核處理器上,此時,程序中的每個線程都 將分配到一個處理器核上,因此可以同時運行。
高并發( High Concurrency): 是互聯網分布式系統架構設計中必須考慮的因素之一,它通常是指通過設計保證系統能夠"同時并行處理"很多請求
- 并發:多個線程操作相同的資源,保證線程安全,合理使用資源
- 高并發:服務能同時處理很多請求,提高程序性能
并發問題模擬
首先說明如下代碼是存在并發問題的,這里是為了拋出問題,后續給出解決辦法.
其中用到的ExecutorService、Semaphore和CountDownLatch等先有個印象,后續深入探討,更多說明見注釋
Spring Boot搭建的工程,詳見github ConcurrencyMaster
package com.artisan;import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore;import lombok.extern.slf4j.Slf4j;/*** 首先說明如下代碼是存在并發問題的,這里是為了拋出問題,后續給出解決辦法* * 要求: 10000個請求,同一時間允許500個請求同時執行 即每次允許500個請求同時執行* * 實現:使用線程池和信號量和countDownLatch模擬客戶端總共發出了1萬個請求,每次允許500個請求同時執行,觀察一共執行了個多少個請求* * @author yangshangwei**/ @Slf4j public class CountCaculatorDemo {// 請求總數private static int clientTotal = 10000;// 同一時間執行的請求數private static int threadTotal = 1;// 計數標識private static int count = 0;public static void main(String[] args) throws InterruptedException {// 創建一個可緩存線程池,如果線程池長度超過實際需要,可靈活回收空閑線程,若無可回收的線程,則新建線程。ExecutorService executorService = Executors.newCachedThreadPool();// 信號量 同一時間允許threadTotal個請求同時執行 即初始化threadTotal個信號量final Semaphore semaphore = new Semaphore(threadTotal);// CountDownLatch是一個同步工具類,它允許一個或多個線程一直等待,直到其他線程的操作執行完后再執行// 定義clientTotal個線程需要執行完,主線程才能繼續執行final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);// 創建clientTotal個線程,模擬clientTotal個請求for (int i = 0; i < clientTotal; i++) {// 執行一個線程 ,count加1executorService.execute(() -> {try {// 獲取許可,獲取許可后執行add方法, 在獲得許可之前,一直將線程阻塞semaphore.acquire();add();// 釋放許可,并將其返回給信號量semaphore.release();} catch (InterruptedException e) {e.printStackTrace();}// 【在循環內】每當一個線程完成了自己的任務后,計數器的值就會減1,這里指的是初始化CountDownLatch給定的clientTotal減一countDownLatch.countDown();});}// 主線程必須在啟動其他線程后立即調用CountDownLatch.await()方法。// 這樣主線程的操作就會在這個方法上阻塞,直到其他線程完成各自的任務。// 當全部線程都調用了countDown方法,count的值等于0,然后主線程就能通過await()方法,恢復執行自己的任務。countDownLatch.await();// 關閉線程池executorService.shutdown();// 打印總數log.info("執行總數:{}", count);}private static void add() {count++;}}執行多次,可以發現絕大部分情況下結果都不為1萬,當然了也有可能為1萬。
如果將threadTotal 改為1 ,即同一時刻只允許一個線程執行,再次運行,無論如何運行多少次,結果都是10000。
說明多線程確實影響到了執行結果,后面繼續將結合Java內存模型分析多線程是如何影響執行結果的。
代碼
https://github.com/yangshangwei/ConcurrencyMaster
總結
以上是生活随笔為你收集整理的并发编程-01并发初窥的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring Boot2.x-12 Sp
- 下一篇: 并发编程-03线程安全性之原子性(Ato