慕课网高并发实战(三)- 项目准备

项目采用springboot基础框架快速开发,具体初始化方法不再赘述,不明白的可以看课程或者自行百度

1. 一些注解的准备

  • 线程安全注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 对于线程安全的类,加入一个@ThreadSafe注解的标示
 * @Target(ElementType.TYPE) 说明作用于类上
 * @Retention(RetentionPolicy.SOURCE) 指定注解作用的范围,在编译的时候就会被忽略掉
 * @author gaowenfeng
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface ThreadSafe {
    String value() default "";
}

复制代码
  • 线程不安全注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 用来标示[线程不安全的类]
 * @Target(ElementType.TYPE) 说明作用于类上
 * @Retention(RetentionPolicy.SOURCE) 指定注解作用的范围,在编译的时候就会被忽略掉
 * @author gaowenfeng
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface NotThreadSafe {
    String value() default "";
}
复制代码
  • 推荐写法注解
/**
 * 用来标记[推荐]的类或者写法
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface Recommend {
    String value() default "";
}
复制代码
  • 不推荐写法注解
/**
 * 用来标记[不推荐]的类或者写法
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface NotRecommend {
    String value() default "";
}
复制代码
  • ElementType 详解
public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
   /** 声明注解作用在类,借口,枚举上*/
    TYPE,

    /** Field declaration (includes enum constants) */
   /** 声明注解作用在属性上*/
    FIELD,

    /** Method declaration */
   /** 声明注解作用在方法上*/
    METHOD,

    /** Formal parameter declaration */
   /** 声明注解作用在参数上*/
    PARAMETER,

    /** Constructor declaration */
   /** 声明注解作用在构造函数上*/
    CONSTRUCTOR,

    /** Local variable declaration */
   /** 声明注解作用在本地变量上*/
    LOCAL_VARIABLE,

    /** Annotation type declaration */
   /** 声明注解作用在注解上*/
    ANNOTATION_TYPE,

    /** Package declaration */
   /** 声明注解作用在包上*/
    PACKAGE,

    /**
     * Type parameter declaration
     *
     * @since 1.8
     */
   /** 声明注解可以应用在TYPE声明上*/
    TYPE_PARAMETER,

    /**
     * Use of a type
     * Type.TYPE_USE 表示这个 Annotation 可以用在所有使用 Type 的地方(如:泛型,类型转换等)
     * @since 1.8
     */
    TYPE_USE
}
复制代码
  • RetentionPolicy详解
public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     * 在编译的时候会被取消,只用于声明,理解,或者测试
     */
    SOURCE,

    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     * 注解将被编译器记录在类文件中,但在运行时不需要由VM保留,(默认的选项)
     */
    CLASS,

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     * 注解将被编译器记录在类文件中,但在运行时由VM保留,这样他们可以被反射获取(当你需要获取注解中字段的属性值的时候,需要用这个,比如AOP)
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}
复制代码

etentionPolicy.SOURCE仅仅是给应用层开发人员用的,RetentionPolicy.CLASS 需要应用层和底层系统开发人员配合使用的,所以仅仅是应用层开发的我们是一脸懵逼,意识CLASS和SOURCE的区别。(具体参考

2.并发模拟

  • 并发模拟工具

  • Postman:Http请求模拟工具

  • Apache附带的工具

# -n  总请求数
# -c  并发数
$ ab -n 1000 -c 50 http://localhost:8080/test
This is ApacheBench, Version 2.3 <$Revision: 1807734 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:
Server Hostname:        localhost
Server Port:            8080

Document Path:          /test
Document Length:        4 bytes

# 并发量
Concurrency Level:      50
# 整个测试耗时
Time taken for tests:   0.285 seconds
# 完成的请求数
Complete requests:      1000
# 失败的请求数
Failed requests:        0
# 所有请求的相应数据的长度综合(HTTP相应数据的 头信息+正文数据的长度)(不包括请求的长度)
Total transferred:      136000 bytes
# 所有请求的相应数据中,正文相应的综合
HTML transferred:       4000 bytes
# 吞吐率(与并发数相关)(Complete requests/0.285 seconds)
Requests per second:    3505.09 [#/sec] (mean)
# 用户平均请求等待时间
Time per request:       14.265 [ms] (mean)
# 服务器平均请求等待时间
Time per request:       0.285 [ms] (mean, across all concurrent requests)
# 这些请求在单位时间内从服务器获取的数据长度(Total transferred/Time taken for tests)
Transfer rate:          465.52 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    5   2.7      5      13
Processing:     1    9   5.0      8      37
Waiting:        1    6   4.0      6      36
Total:          2   14   5.0     14      40

Percentage of the requests served within a certain time (ms)
  50%     14
  66%     15
  75%     16
  80%     17
  90%     19
  95%     21
  98%     30
  99%     34
 100%     40 (longest request)

复制代码
  • JMeter

  • 并发模拟-代码

import com.gwf.concurrency.annoations.NotThreadSafe;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

/**
 * 并发测试
 * @author gaowenfeng
 */
@Slf4j
@NotThreadSafe
public class ConcurrencyTest {

    /** 请求总数 */
    public static int clientTotal = 5000;
    /** 同时并发执行的线程数 */
    public static int threadTotal = 50;

    public static int count = 0;

    public static void main(String[] args) throws InterruptedException {
        // 创建线程池
        ExecutorService executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                60L, TimeUnit.SECONDS,
                new SynchronousQueue<>(), r -> new Thread(r,"测试线程"));
        // 信号量,闭锁
        final Semaphore semaphore = new Semaphore(threadTotal);
        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
        // 模拟并发请求
        for (int i = 0; i < clientTotal; i++) {
            executorService.execute(()->{
                try {
                    // 请求一个信号,如果信号量小于clientTotal,则阻塞
                    semaphore.acquire();
                    add();
                    // 释放一个信号
                    semaphore.release();
                } catch (InterruptedException e) {
                    log.error("exception",e);
                }
                countDownLatch.countDown();
            });
        }
        // 阻塞直到countDown 的次数为threadTotal
        countDownLatch.await();
        // 关闭线程池
        executorService.shutdown();
        log.info("count:{}",count);

    }

    /**
     * 本质上应该是这个方法线程不安全
     */
    private static void add(){
        count++;
    }
}
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值