在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

測試聊并發-入門篇

京東云 ? 來源:京東保險 張新磊 ? 作者:京東保險 張新磊 ? 2024-10-15 15:23 ? 次閱讀

作者:京東保險 張新磊

背景

在現代軟件測試的廣闊領域中,我們的工作不僅限于確保功能符合產品和業務需求的嚴格標準。隨著用戶對應用性能的期望水漲船高,性能測試已成為衡量軟件質量的關鍵指標。特別是在服務端接口的性能測試中,我們面臨的挑戰不僅僅是處理單個請求的效率,更在于如何在多用戶同時訪問時保持系統的穩定性和響應速度。并發編程和測試,作為性能測試的核心,對于評估系統在高負載情況下的表現、識別潛在的性能瓶頸、以及優化資源配置具有至關重要的作用。

并發編程是一門藝術,它要求開發者在多線程或多進程的環境中精心編排代碼,以實現資源的高效共享和任務的并行執行。這不僅需要深厚的編程功底,更需要對并發模型、同步機制和線程安全性有深刻的認識。而在測試領域,性能測試工程師必須精通如何構建并發測試場景,運用工具模擬真實的高并發環境,以及如何從測試結果中提煉出有價值的洞察,以指導性能的持續優化。

本文將深入剖析并發編程的深層原理、面臨的挑戰以及采納的最佳實踐。同時,我們將探討并發測試的策略、工具和技術,并通過實際案例的分析,闡釋如何在軟件開發生命周期中有效地整合并發測試,以及如何利用并發測試來顯著提升系統的性能和可靠性。

wKgaomcOGIaAYRRFAA8I_5ZNG3k231.jpg

多線程基礎和作用

進程與線程的區別

wKgZomcOGIeAZcRUAAW-odY7m30058.jpg


資源分配:進程是資源分配的基本單位,線程是CPU調度和執行的基本單位。
獨立性:進程是獨立運行的,而線程則依賴于進程。
內存分配:進程有自己的內存空間,線程共享進程的內存空間。
開銷:線程的創建和切換開銷小于進程。
并發性:線程可以提高程序的并發性,因為它們可以并行執行。

Java中線程的創建方式

方式一.繼承Thread
當你創建一個繼承自Thread類的子類時,你需要重寫run方法,該方法包含了線程要執行的代碼。然后,你可以通過創建這個子類的實例并調用其start方法來啟動線程。

class MyThread extends Thread {
    @Override
    public void run() {
        // 線程要執行的代碼
        System.out.println("線程運行中...");
    }
}

public class ThreadExample {
    public static void main(String[] args) {
        MyThread t = new MyThread();
        t.start(); // 啟動線程
    }
}

方式二.實現Runnable接口
另一種創建線程的方式是實現Runnable接口。你需要創建一個實現了Runnable接口的類,然后創建該類的實例,并把這個實例傳遞給Thread類的構造函數。最后,通過調用Thread對象的start方法來啟動線程。

class MyRunnable implements Runnable {
    @Override
    public void run() {
        // 線程要執行的代碼
        System.out.println("線程運行中...");
    }
}

public class RunnableExample {
    public static void main(String[] args) {
        MyRunnable r = new MyRunnable();
        Thread t = new Thread(r);
        t.start(); // 啟動線程
    }
}

比較兩種方式
靈活性:實現Runnable接口比繼承Thread類更靈活,因為Java不支持多重繼承,但可以實現多個接口。
資源管理:如果你需要多個線程共享同一個資源,實現Runnable接口是更好的選擇,因為你可以定義一個資源類,然后創建多個Runnable實例來共享這個資源。
代碼重用:實現Runnable接口允許你將線程的運行代碼與線程的控制代碼分離,這有助于代碼重用。
在實際開發中,推薦使用實現Runnable接口的方式來創建線程,因為它提供了更好的靈活性和代碼重用性,但也需考慮實際情況選擇使用。

線程生命周期

wKgaomcOGImAVYsTAAWkaVSPzxw031.jpg

新建(New)、可運行(Runnable)、阻塞(Blocked)、正在運行(Running)、終止(Terminated)等狀態的解釋。
新建(New):
線程對象已經被創建,但還沒有調用start()方法。在這個狀態下,線程還沒有開始執行。
可運行(Runnable):
線程已經調用了start()方法,此時線程處于可運行狀態。可運行狀態包括了操作系統線程的就緒(Ready)和運行(Running)狀態。線程可能正在運行,也可能正在等待CPU時間片,因為可運行狀態的線程會與其他線程共享CPU資源。
阻塞(Blocked):
線程因為等待一個監視器鎖(比如進入一個同步塊)而無法繼續執行的狀態。在這種情況下,線程會一直等待直到獲取到鎖。阻塞狀態通常發生在多個線程嘗試進入一個同步方法或同步塊時,但只有一個線程能夠獲得鎖。
正在運行(Running):
線程正在執行其run()方法的代碼。這個狀態是可運行狀態的一個子集,表示線程當前正在CPU上執行。
注意:在Java官方文檔中,并沒有明確區分“可運行”和“正在運行”這兩個狀態,通常將它們統稱為“可運行(Runnable)”狀態。
終止(Terminated):
線程的運行結束。這可能是因為線程正常執行完任務,或者因為某個未捕獲的異常導致線程結束。一旦線程進入終止狀態,它就不能再被啟動或恢復。

線程同步

同步指的是在多線程環境中,控制多個線程對共享資源的訪問順序,以防止數據不一致和競態條件。同步機制確保了當一個線程訪問某個資源時,其他線程不能同時訪問該資源。
數據一致性:防止多個線程同時修改同一數據,導致數據不一致。
線程安全:確保程序在多線程環境下能夠正確運行,不會因為線程的并行執行而出現錯誤。
性能優化:合理的同步可以提高程序的并發性能,避免不必要的線程阻塞和上下文切換。
synchronized關鍵字的使用
synchronized 是 Java 中用于同步的一個關鍵字,它可以用于方法或代碼塊,確保同一時間只有一個線程可以執行該段代碼。

同步方法
public synchronized void myMethod() {
    // 需要同步的代碼
}
同步代碼塊
public void myMethod() {
    synchronized(this) {
        // 需要同步的代碼
    }
}

Locks&ReentrantLock
Java 提供了更靈活的鎖機制,稱為 Locks,其中最常用的是 ReentrantLock。
Locks:提供了比 synchronized 更靈活的鎖定機制,如嘗試鎖定、定時鎖定、可中斷的鎖定等。
ReentrantLock:是一種可重入的互斥鎖,支持完全的鎖定操作,可以被同一個線程多次獲得,但必須釋放相同次數。
使用 ReentrantLock 的基本步驟:
創建 ReentrantLock 對象。
在需要同步的代碼塊前后調用 lock() 和 unlock() 方法。
確保在 finally 塊中釋放鎖,以避免死鎖

import java.util.concurrent.locks.ReentrantLock;
public class Example {
    private final ReentrantLock lock = new ReentrantLock();
    public void myMethod() {
        lock.lock();
        try {
            // 需要同步的代碼
        } finally {
            lock.unlock();
        }
    }
}

線程同步是確保多線程程序正確性和性能的關鍵技術。synchronized 和 ReentrantLock 提供了不同的同步機制,開發者可以根據具體需求選擇合適的同步方式。正確使用同步機制可以避免數據不一致和競態條件,提高程序的穩定性和性能。

線程間通信

線程間通信是多線程編程中的一個重要概念,它允許線程之間進行數據交換和狀態同步。在 Java 中,線程間通信主要通過等待/通知機制和條件變量來實現。

等待/通知機制(wait()、notify()、notifyAll())

wait():當一個線程調用 wait() 方法時,它會釋放對象的鎖,并進入該對象的等待池(wait set)中等待。其他線程可以調用 notify() 或 notifyAll() 方法來喚醒等待池中的線程。
notify():喚醒在該對象上等待的單個線程。選擇哪個線程是不確定的。
notifyAll():喚醒在該對象上等待的所有線程。

public class Message {
    private String content;
    private boolean empty = true;

    public synchronized String take() throws InterruptedException {
        while (empty) {
            wait();
        }
        empty = true;
        notifyAll();
        return content;
    }

    public synchronized void put(String content) throws InterruptedException {
        while (!empty) {
            wait();
        }
        empty = false;
        this.content = content;
        notifyAll();
    }
}

條件變量(Condition)

條件變量提供了一種更靈活的線程間通信方式。Condition 接口是 java.util.concurrent.locks 包的一部分,它與 Lock 接口一起使用。
await():類似于 wait(),但需要在 Condition 對象上調用。
signal():類似于 notify(),但需要在 Condition 對象上調用。
signalAll():類似于 notifyAll(),但需要在 Condition 對象上調用。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Message {
    private String content;
    private boolean empty = true;
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition notEmpty = lock.newCondition();

    public void put(String content) throws InterruptedException {
        lock.lock();
        try {
            while (!empty) {
                notEmpty.await();
            }
            empty = false;
            this.content = content;
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    public String take() throws InterruptedException {
        lock.lock();
        try {
            while (empty) {
                notEmpty.await();
            }
            empty = true;
            String result = content;
            notEmpty.signal();
            return result;
        } finally {
            lock.unlock();
        }
    }
}

線程池


線程池是一種執行器(Executor),用于在一個后臺線程中執行任務。線程池的主要目的是減少在創建和銷毀線程時所產生的性能開銷。通過重用已經創建的線程來執行新的任務,線程池提高了程序的響應速度,并且提供了更好的系統資源管理。

Executor框架的使用

Java的java.util.concurrent包提供了Executor框架,它是一個用于管理線程的框架,包括線程池的管理。Executor框架的核心接口是Executor和ExecutorService。
Executor:一個執行提交的Runnable任務的接口。
ExecutorService:Executor的子接口,提供了管理任務生命周期的方法,如關閉線程池、提交異步任務等。

如何創建和使用不同類型的線程池

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExample {
    public static void main(String[] args) {
        // 創建一個固定大小的線程池
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);

        // 創建一個緩存線程池
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

        // 創建一個單線程池
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

        // 提交任務給線程池
        for (int i = 0; i < 10; i++) {
            final int index = i;
            fixedThreadPool.submit(() -?> {
                System.out.println("執行任務:" + index + " 線程:" + Thread.currentThread().getName());
            });
        }

        // 關閉線程池
        fixedThreadPool.shutdown();
        cachedThreadPool.shutdown();
        singleThreadExecutor.shutdown();
    }
}

并發集合

傳統的集合類在多線程環境下的問題

傳統的集合類(如 ArrayList、LinkedList、HashMap 等)并不是線程安全的。這意味著,如果在多線程環境下,多個線程同時對這些集合進行讀寫操作,可能會導致以下幾種問題
數據不一致:當多個線程同時修改集合時,可能會導致集合的狀態不一致。例如,一個線程正在遍歷列表,而另一個線程正在添加或刪除元素,這可能導致遍歷過程中出現 ConcurrentModificationException。
競態條件:當多個線程并發訪問集合并且至少有一個線程在修改集合時,就會發生競態條件。這意味著最終結果依賴于線程執行的順序,這可能導致不可預測的結果。
臟讀:一個線程可能讀取到另一個線程修改了一半的數據,這種讀取被稱為“臟讀”。
幻讀:在一個事務中,多次查詢數據庫,由于其他事務插入了行,導致原本滿足條件的查詢結果集中出現了“幻影”行。
不可重復讀:在一個事務內,多次讀取同一數據集合,由于其他線程的修改,導致每次都得到不同的數據,這被稱為不可重復讀。

通過以下幾種策略解決多線程環境問題

使用同步包裝器:Java提供了一些同步包裝器,如 Collections.synchronizedList、Collections.synchronizedMap 等,可以將非線程安全的集合包裝成線程安全的。
使用并發集合:Java的 java.util.concurrent 包提供了一些線程安全的集合類,如 ConcurrentHashMap、CopyOnWriteArrayList 等,它們內部實現了必要的同步機制。
使用鎖:可以使用 synchronized 關鍵字或 ReentrantLock 對集合的操作進行顯式同步。
使用原子類:對于基本數據類型的集合,可以使用 java.util.concurrent.atomic 包中的原子類,如 AtomicInteger、AtomicReference 等。
使用不可變集合:不可變集合一旦創建就不能被修改,因此是線程安全的。可以使用 Collections.unmodifiableList、Collections.unmodifiableMap 等方法創建不可變集合。
使用線程局部變量:如果每個線程都需要有自己的集合副本,可以使用 ThreadLocal 類。
避免共享:如果可能,避免在多個線程間共享集合,每個線程使用獨立的集合可以避免同步問題。

并發設計模式

生產者-消費者模式(Producer-Consumer Pattern)

生產者-消費者模式是一種常見的并發設計模式,用于協調生產者線程和消費者線程之間的工作。生產者線程負責生成數據,消費者線程負責處理數據。它們之間通常通過一個共享的緩沖區(如隊列)進行通信。這個模式可以有效地解耦生產者和消費者的工作,提高程序的并發性能。

BlockingQueue queue = new LinkedBlockingQueue();

class Producer extends Thread {
    public void run() {
        while (true) {
            Work item = produce();
            queue.put(item);
        }
    }

    Work produce() {
        // 生產數據
        return new Work();
    }
}

class Consumer extends Thread {
    public void run() {
        while (true) {
            Work item = queue.take();
            consume(item);
        }
    }

    void consume(Work item) {
        // 消費數據
    }
}

讀寫鎖模式(Reader-Writer Lock Pattern)

讀寫鎖模式允許多個線程同時讀取共享資源,但寫入操作是互斥的。這種模式適用于讀多寫少的場景,可以提高程序的并發性能。

class ReadWriteResource {
    private final ReadWriteLock lock = new ReentrantReadWriteLock();

    public void read() {
        lock.readLock().lock();
        try {
            // 執行讀取操作
        } finally {
            lock.readLock().unlock();
        }
    }

    public void write() {
        lock.writeLock().lock();
        try {
            // 執行寫入操作
        } finally {
            lock.writeLock().unlock();
        }
    }
}

線程池模式(ThreadPool Pattern)

線程池模式通過復用一組線程來執行多個任務,減少了線程創建和銷毀的開銷。線程池可以控制并發線程的數量,提高資源利用率。

ExecutorService executor = Executors.newFixedThreadPool(10);
executor.submit(() -> {
    // 執行任務
});

executor.shutdown();

案例分析

寫了幾個多線程并發的小demo,有需要可以聯系獲取倉庫權限

注:文章有很多瑕疵,歡迎各位大佬批評指正

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 測試
    +關注

    關注

    8

    文章

    5399

    瀏覽量

    127128
  • 代碼
    +關注

    關注

    30

    文章

    4837

    瀏覽量

    69128
收藏 人收藏

    評論

    相關推薦

    松下MPS媒體制作平臺第七:視頻混合器插件(第二部分)

    分的MPS媒體制作平臺教程,本期是第二部分。在進入本部分之前,請參考之前的視頻做好相應的準備設置工作。 ◎松下MPS媒體制作平臺入門篇:下載、安裝及激活教程 ◎松下MPS媒體制作平臺第二:設備查看 ◎松下MPS媒體制作平臺第三
    的頭像 發表于 12-19 13:38 ?211次閱讀
    松下MPS媒體制作平臺第七<b class='flag-5'>篇</b>:視頻混合器插件(第二部分)

    超詳細“零”基礎kafka入門篇

    1、認識kafka 1.1 kafka簡介 Kafka?是一個分布式流媒體平臺 kafka官網:http://kafka.apache.org/ (1)流媒體平臺有三個關鍵功能: 發布和訂閱記錄流 ,類似于消息隊列或企業消息傳遞系統。 以 容錯的持久方式存儲記錄流 。 記錄發生時處理流。 (2)Kafka通常用于兩大類應用: 構建可在 系統或應用程序之間 可靠獲取數據的實時流數據管道 構建轉換或響應數據流的實時流應用程序 要了解Kafka如何做這些事情,讓我們深入探討Kafka的能力。 (3)首先是幾個概念:
    的頭像 發表于 12-18 09:50 ?983次閱讀
    超詳細“零”基礎kafka<b class='flag-5'>入門篇</b>

    零基礎開發小安派-Eyes-S1【入門篇】——工程文件架構

    -Eyes-S1【入門篇】——初識小安派-Eyes-S12、零基礎開發小安派-Eyes-S1【入門篇】——安裝VMware與Ubuntu3、入門篇:零基礎開發小安派-Eyes-S1——新建工程并燒錄調試4
    的頭像 發表于 11-06 16:10 ?228次閱讀
    零基礎開發小安派-Eyes-S1【<b class='flag-5'>入門篇</b>】——工程文件架構

    迅為iTOP-RK3568開發板驅動開發指南-第十八 PWM

    教程概覽 文檔教程更新至第18-PWM 第1 驅動基礎 第2 字符設備基礎 第3 并發
    發表于 10-29 10:13

    【AG32開發板體驗連載】網絡攝像頭

    圖是 AGM 開發板,核心處理器為 AGM32VF407VGT6,1M Flash + 128K SRAM,還附帶了 USB 線等線材,開盒即用 【入門篇】 AGM32VF407VGT6
    發表于 10-11 14:54

    重塑定位邊界:革新 UWB 信標定位系統測試套件,精準并發融合引領未來

    面對日益復雜多變的應用場景及高并發需求的激增,巍泰技術特隆重推出采用 TurMass 無線通信技術的 UWB 信標定位系統測試套件 WTS-102 ,為各類復雜應用場景提供持續、可靠、精準的定位服務。
    的頭像 發表于 09-23 15:13 ?792次閱讀
    重塑定位邊界:革新 UWB 信標定位系統<b class='flag-5'>測試</b>套件,精準<b class='flag-5'>并發</b>融合引領未來

    并發物聯網云平臺是什么

    并發物聯網云平臺是一種能夠處理大量設備同時連接并進行數據交換的云計算平臺。這種平臺通常被設計用來應對來自數以萬計甚至數十億計的物聯網設備的并發請求,保證系統的穩定性和響應速度。 首先,從技術層面
    的頭像 發表于 08-13 13:50 ?307次閱讀

    并發系統的藝術:如何在流量洪峰中游刃有余

    前言 我們常說的三高,高并發、高可用、高性能,這些技術是構建現代互聯網應用程序所必需的。對于京東618備戰來說,所有的中臺系統服務,無疑都是圍繞著三高來展開的。而對于京東龐大的客戶群體,高并發的要求
    的頭像 發表于 08-05 13:43 ?336次閱讀
    高<b class='flag-5'>并發</b>系統的藝術:如何在流量洪峰中游刃有余

    【《大語言模型應用指南》閱讀體驗】+ 俯瞰全書

    松。 入門篇主要偏應用,比如大語言模型的三種交互方式,分析了提示工程、工作記憶和長短期記憶,此最后講了ChatGPT的接口和擴展功能應用,適合大語言模型應用技術人員閱讀。 進階就非常專業了,適合專業
    發表于 07-21 13:35

    文檔更新 |迅為 RK3568開發板驅動指南-第十五/十六

    《iTOP-RK3568開發板驅動開發指南》更新,本次更新內容對應的是驅動(第十五 i2C)(第十六 SPI)視頻,后續資料會不斷更新,不斷完善,幫助用戶快速入門,大大提升研發速度。 教程概覽
    發表于 07-08 11:04

    性能測試主要測什么 性能測試的指標有哪些

    。 性能測試的主要測試內容 響應時間 :評估系統在特定操作下的反應速度,通常以毫秒為單位。 吞吐量 :衡量系統在單位時間內能夠處理的事務數量或請求數。 并發用戶數 :測試系統在同時處理
    的頭像 發表于 05-29 15:42 ?2620次閱讀

    “阻抗修正”去嵌入

    在非標準接口器件測試中,使用去嵌入方法消除測試夾具等對測試結果的影響已經被很多小伙伴們熟知。在最新的R&S ZNA/ZNB系列矢量網絡分析儀(簡稱:矢網)界面中,加入了“Deembed Assistant(去嵌助手)”,可以幫助
    的頭像 發表于 04-17 14:18 ?1503次閱讀
    <b class='flag-5'>聊</b>一<b class='flag-5'>聊</b>“阻抗修正”去嵌入

    巨霖科技將亮相IIC Shanghai并發表主題演講

    活動預告∣巨霖科技將亮相IIC Shanghai 并發表主題演講
    的頭像 發表于 03-27 09:50 ?454次閱讀
    巨霖科技將亮相IIC Shanghai<b class='flag-5'>并發</b>表主題演講

    stm32wb55rg ZigBee和藍牙并發運行時,連接藍牙失敗的原因?怎么解決?

    在使用rt thread系統移植官方ZigBee_ble_dynamic的示例程序時,兩者都能并發廣播,但是一旦到藍牙連接時,系統就會停止,一直卡在ZbStartupWait info-&
    發表于 03-15 07:59

    HarmonyOS如何使用異步并發能力進行開發

    一、并發概述 并發是指在同一時間段內,能夠處理多個任務的能力。為了提升應用的響應速度與幀率,以及防止耗時任務對主線程的干擾,HarmonyOS系統提供了異步并發和多線程并發兩種處理策略
    的頭像 發表于 02-18 09:18 ?596次閱讀
    主站蜘蛛池模板: 精品国产亚洲人成在线 | 第四色播日韩第一页 | 97爱爱爱| 丝袜美女被c | 97一本大道波多野吉衣 | 美女久久久 | bl高h文| 国产成人精品本亚洲 | 五月婷婷色综合 | 不卡午夜 | 两人性潮高免费视频看 | 在线小毛片| 国产va精品免费观看 | 日本黄色电影在线 | 艹逼视频免费 | 久久综合狠狠综合久久综合88 | 美女毛片视频 | 国产色视频网站免费观看 | 亚洲精品午夜久久aaa级久久久 | 午夜三级视频 | 国产一级特黄特色aa毛片 | 日本黄色免费在线观看 | www.91久久| 日本视频一区在线观看免费 | 国产va在线播放 | 欧美在线视频二区 | 亚洲伊人久久大香线蕉影院 | h视频免费看 | 欧美一级特黄视频 | 午夜一级毛片 | 色婷婷综合久久久久中文一区二区 | 一级a毛片免费 | 日本成人一级片 | 2022年国产精品久久久久 | a爱视频 | 欧美啪啪小视频 | 操国产美女 | 国产精品免费看久久久香蕉 | 免费黄色成人 | 亚洲综合久久久久久888 | 久精品视频村上里沙 |