1. 程式人生 > >java併發模擬——多執行緒計數

java併發模擬——多執行緒計數

java併發模擬——多執行緒計數

最近在學習多執行緒與高併發的知識,這是一個能力進階的必要途徑。在大量的系統中,都會多多少少存在併發問題,如何更好的解決高併發是一個探究的問題。
下面我準備了一個簡單的多執行緒計數demo來模擬併發操作,觀察列印輸出情況,真正的去感受一下併發操作。
首先環境搭建,我用的是springboot,在spring官網或者idea中初始化一個maven專案
在這裡插入圖片描述生成專案之後,先配置pom.xml,新增相關的依賴,pom.xml:
重點是添加了lombok依賴,有關日誌列印的,其他沒有的自行加入。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.1.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>concurrency</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>
	<name>concurrency</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.16.10</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>

然後我們在看主函式,新建一個類ConcurrencyTest,引入Slf4j註解,定義執行緒池,訊號量,初始計數,日誌,請求總數,一次請求允許的併發數(即執行緒數)等。每一個請求時,所有執行緒同時執行add操作,我們來看最後會執行多少次。程式碼如下:

package com.example.concurrency;



import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.*;


@Slf4j
public class ConcurrencyTtest {
    //請求總數
    public static int clientTotal=5000;
    //同時併發執行的執行緒數
    public static int threadTotal=200;
    //一開始計數為0
    public static int count=0;
    //定義一個日誌
    private static Logger log= LoggerFactory.getLogger(ConcurrencyTtest.class);

    public static void main(String []args) throws InterruptedException {
        //定義執行緒池
        ExecutorService executorService= Executors.newCachedThreadPool();
        //定義一個threadTotal的訊號量
        final Semaphore semaphore=new Semaphore(threadTotal);
        //定義一個計數遞減鎖
        final CountDownLatch countDownLatch=new CountDownLatch(clientTotal);
        for(int i=0;i<clientTotal;i++) {
            executorService.execute(() -> {
                try {
                    semaphore.acquire();
                    add();
                    semaphore.release();
                } catch (Exception e) {
                   log.error("exception",e);
                }
                //
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        executorService.shutdown();
        log.error("count:{}"+count);
    }
    //加1操作
    public static void add(){
        count++;
    }
}

我們來執行一下結果(連續執行三次,看結果)
在這裡插入圖片描述

在這裡插入圖片描述

在這裡插入圖片描述
我們發現,每次結果都不同,正常情況下,我們想如果只有一個程序,那麼結果肯定是5000,不會出現錯誤情況。這就是當執行緒數增多,併發量增多,導致程式出錯,系統出錯。在實際的大型專案中,這種情況經常出現,我們也要不斷的去應付高併發的情況,提出相應的解決方案。後續的我會不斷給出高併發的相關知識以及解決方案。