前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >慕课网高并发实战(三)- 项目准备

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

作者头像
Meet相识
发布2018-09-12 16:39:06
8680
发布2018-09-12 16:39:06
举报
文章被收录于专栏:技术专栏

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

1. 一些注解的准备

  • 线程安全注解
代码语言:javascript
复制
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 "";
}
  • 线程不安全注解
代码语言:javascript
复制
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 "";
}
  • 推荐写法注解
代码语言:javascript
复制
/**
 * 用来标记[推荐]的类或者写法
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface Recommend {
    String value() default "";
}
  • 不推荐写法注解
代码语言:javascript
复制
/**
 * 用来标记[不推荐]的类或者写法
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface NotRecommend {
    String value() default "";
}
  • ElementType 详解
代码语言:javascript
复制
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详解
代码语言:javascript
复制
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请求模拟工具

postman

  • Apache附带的工具

AB

代码语言:javascript
复制
# -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

JMeter

创建线程组

创建HTTP请求

创建监视器

log

  • 并发模拟-代码

CountDownLatch

Semaphore

代码语言:javascript
复制
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++;
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.03.17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 一些注解的准备
  • 2.并发模拟
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档