一,JMH

Java Microbenchmark Harness,是Java用来做基准测试的工具,测试结果可信度高,用于测试某个方法的性能。13年首发,由JIT开发人员开发,后归于OpenJDK。

官网:OpenJDK: jmh

官方样例: code-tools/jmh: 2be2df7dbaf8 /jmh-samples/src/main/java/org/openjdk/jmh/samples/

(一)创建JMH测试

需要准确的效果,建议是用命令行的方式,并独一代码单独打包进行测试。

如果想边开发边测试(我是懒得重弄项目了),可以使用JMH的插件。

1,idea安装JMH插件   idea18  版本,装的这个

2,MAVEN

 <!--jmh--><!-- https://mvnrepository.com/artifact/org.openjdk.jmh/jmh-core --><dependency><groupId>org.openjdk.jmh</groupId><artifactId>jmh-core</artifactId><version>1.21</version></dependency><!-- https://mvnrepository.com/artifact/org.openjdk.jmh/jmh-generator-annprocess --><dependency><groupId>org.openjdk.jmh</groupId><artifactId>jmh-generator-annprocess</artifactId><version>1.21</version><scope>test</scope></dependency>

3,由于用到了注解,打开运行程序注解配置

compiler -> Annotation Processors -> Enable Annotation Processing

5,测试类

package com.example.demo.jmh;import java.util.ArrayList;
import java.util.List;
import java.util.Random;public class PS {static List<Integer> nums = new ArrayList<>();static {Random r = new Random();for (int i = 0; i < 10000; i++) nums.add(1000000 + r.nextInt(1000000));}static void foreach() {nums.forEach(v->isPrime(v));}static void parallel() {nums.parallelStream().forEach(PS::isPrime);}static boolean isPrime(int num) {for(int i=2; i<=num/2; i++) {if(num % i == 0) return false;}return true;}
}

6,单元测试

package com.example.demo.jmh;import org.openjdk.jmh.annotations.Benchmark;public class PSTest {@Benchmarkpublic void testForEach() {PS.foreach();}
}

7,运行测试类,如果遇到下面的错误:

 ERROR: org.openjdk.jmh.runner.RunnerException: ERROR: Exception while trying to acquire the JMH lock (C:\WINDOWS\/jmh.lock): C:\WINDOWS\jmh.lock (拒绝访问。), exiting. Use -Djmh.ignoreLock=true to forcefully continue.at org.openjdk.jmh.runner.Runner.run(Runner.java:216)at org.openjdk.jmh.Main.main(Main.java:71)

这个错误是因为JMH运行需要访问系统的TMP目录,解决办法是:

打开RunConfiguration -> Environment Variables -> include system environment viables

 

8,阅读测试报告

"C:\Program Files\Java\jdk1.8.0_171\bin\java.exe" -Dfile.encoding=UTF-8 -classpath "D:\Program Files\JetBrains\idea18\work\learnRecords\target\test-classes;D:\Program Files\JetBrains\idea18\work\learnRecords\target\classes;C:\Users\jinyh\.m2\repository\org\springframework\boot\spring-boot-starter\2.5.3\spring-boot-starter-2.5.3.jar;C:\Users\jinyh\.m2\repository\org\springframework\boot\spring-boot\2.5.3\spring-boot-2.5.3.jar;C:\Users\jinyh\.m2\repository\org\springframework\spring-context\5.3.9\spring-context-5.3.9.jar;C:\Users\jinyh\.m2\repository\org\springframework\spring-aop\5.3.9\spring-aop-5.3.9.jar;C:\Users\jinyh\.m2\repository\org\springframework\spring-beans\5.3.9\spring-beans-5.3.9.jar;C:\Users\jinyh\.m2\repository\org\springframework\spring-expression\5.3.9\spring-expression-5.3.9.jar;C:\Users\jinyh\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\2.5.3\spring-boot-autoconfigure-2.5.3.jar;C:\Users\jinyh\.m2\repository\org\springframework\boot\spring-boot-starter-logging\2.5.3\spring-boot-starter-logging-2.5.3.jar;C:\Users\jinyh\.m2\repository\ch\qos\logback\logback-classic\1.2.4\logback-classic-1.2.4.jar;C:\Users\jinyh\.m2\repository\ch\qos\logback\logback-core\1.2.4\logback-core-1.2.4.jar;C:\Users\jinyh\.m2\repository\org\apache\logging\log4j\log4j-to-slf4j\2.14.1\log4j-to-slf4j-2.14.1.jar;C:\Users\jinyh\.m2\repository\org\apache\logging\log4j\log4j-api\2.14.1\log4j-api-2.14.1.jar;C:\Users\jinyh\.m2\repository\org\slf4j\jul-to-slf4j\1.7.32\jul-to-slf4j-1.7.32.jar;C:\Users\jinyh\.m2\repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;C:\Users\jinyh\.m2\repository\org\springframework\spring-core\5.3.9\spring-core-5.3.9.jar;C:\Users\jinyh\.m2\repository\org\springframework\spring-jcl\5.3.9\spring-jcl-5.3.9.jar;C:\Users\jinyh\.m2\repository\org\yaml\snakeyaml\1.28\snakeyaml-1.28.jar;C:\Users\jinyh\.m2\repository\org\springframework\boot\spring-boot-starter-test\2.5.3\spring-boot-starter-test-2.5.3.jar;C:\Users\jinyh\.m2\repository\org\springframework\boot\spring-boot-test\2.5.3\spring-boot-test-2.5.3.jar;C:\Users\jinyh\.m2\repository\org\springframework\boot\spring-boot-test-autoconfigure\2.5.3\spring-boot-test-autoconfigure-2.5.3.jar;C:\Users\jinyh\.m2\repository\com\jayway\jsonpath\json-path\2.5.0\json-path-2.5.0.jar;C:\Users\jinyh\.m2\repository\net\minidev\json-smart\2.4.7\json-smart-2.4.7.jar;C:\Users\jinyh\.m2\repository\net\minidev\accessors-smart\2.4.7\accessors-smart-2.4.7.jar;C:\Users\jinyh\.m2\repository\org\ow2\asm\asm\9.1\asm-9.1.jar;C:\Users\jinyh\.m2\repository\jakarta\xml\bind\jakarta.xml.bind-api\2.3.3\jakarta.xml.bind-api-2.3.3.jar;C:\Users\jinyh\.m2\repository\jakarta\activation\jakarta.activation-api\1.2.2\jakarta.activation-api-1.2.2.jar;C:\Users\jinyh\.m2\repository\org\assertj\assertj-core\3.19.0\assertj-core-3.19.0.jar;C:\Users\jinyh\.m2\repository\org\hamcrest\hamcrest\2.2\hamcrest-2.2.jar;C:\Users\jinyh\.m2\repository\org\junit\jupiter\junit-jupiter\5.7.2\junit-jupiter-5.7.2.jar;C:\Users\jinyh\.m2\repository\org\junit\jupiter\junit-jupiter-api\5.7.2\junit-jupiter-api-5.7.2.jar;C:\Users\jinyh\.m2\repository\org\apiguardian\apiguardian-api\1.1.0\apiguardian-api-1.1.0.jar;C:\Users\jinyh\.m2\repository\org\opentest4j\opentest4j\1.2.0\opentest4j-1.2.0.jar;C:\Users\jinyh\.m2\repository\org\junit\platform\junit-platform-commons\1.7.2\junit-platform-commons-1.7.2.jar;C:\Users\jinyh\.m2\repository\org\junit\jupiter\junit-jupiter-params\5.7.2\junit-jupiter-params-5.7.2.jar;C:\Users\jinyh\.m2\repository\org\junit\jupiter\junit-jupiter-engine\5.7.2\junit-jupiter-engine-5.7.2.jar;C:\Users\jinyh\.m2\repository\org\junit\platform\junit-platform-engine\1.7.2\junit-platform-engine-1.7.2.jar;C:\Users\jinyh\.m2\repository\org\mockito\mockito-core\3.9.0\mockito-core-3.9.0.jar;C:\Users\jinyh\.m2\repository\net\bytebuddy\byte-buddy\1.10.22\byte-buddy-1.10.22.jar;C:\Users\jinyh\.m2\repository\net\bytebuddy\byte-buddy-agent\1.10.22\byte-buddy-agent-1.10.22.jar;C:\Users\jinyh\.m2\repository\org\objenesis\objenesis\3.2\objenesis-3.2.jar;C:\Users\jinyh\.m2\repository\org\mockito\mockito-junit-jupiter\3.9.0\mockito-junit-jupiter-3.9.0.jar;C:\Users\jinyh\.m2\repository\org\skyscreamer\jsonassert\1.5.0\jsonassert-1.5.0.jar;C:\Users\jinyh\.m2\repository\com\vaadin\external\google\android-json\0.0.20131108.vaadin1\android-json-0.0.20131108.vaadin1.jar;C:\Users\jinyh\.m2\repository\org\springframework\spring-test\5.3.9\spring-test-5.3.9.jar;C:\Users\jinyh\.m2\repository\org\xmlunit\xmlunit-core\2.8.2\xmlunit-core-2.8.2.jar;C:\Users\jinyh\.m2\repository\net\sourceforge\jexcelapi\jxl\2.6.12\jxl-2.6.12.jar;C:\Users\jinyh\.m2\repository\log4j\log4j\1.2.14\log4j-1.2.14.jar;C:\Users\jinyh\.m2\repository\org\apache\zookeeper\zookeeper\3.4.6\zookeeper-3.4.6.jar;C:\Users\jinyh\.m2\repository\org\slf4j\slf4j-api\1.7.32\slf4j-api-1.7.32.jar;C:\Users\jinyh\.m2\repository\org\slf4j\slf4j-log4j12\1.7.32\slf4j-log4j12-1.7.32.jar;C:\Users\jinyh\.m2\repository\jline\jline\0.9.94\jline-0.9.94.jar;C:\Users\jinyh\.m2\repository\junit\junit\4.13.2\junit-4.13.2.jar;C:\Users\jinyh\.m2\repository\org\hamcrest\hamcrest-core\2.2\hamcrest-core-2.2.jar;C:\Users\jinyh\.m2\repository\io\netty\netty\3.7.0.Final\netty-3.7.0.Final.jar;C:\Users\jinyh\.m2\repository\javax\servlet\servlet-api\2.5\servlet-api-2.5.jar;C:\Users\jinyh\.m2\repository\org\openjdk\jmh\jmh-core\1.21\jmh-core-1.21.jar;C:\Users\jinyh\.m2\repository\net\sf\jopt-simple\jopt-simple\4.6\jopt-simple-4.6.jar;C:\Users\jinyh\.m2\repository\org\apache\commons\commons-math3\3.2\commons-math3-3.2.jar;C:\Users\jinyh\.m2\repository\org\openjdk\jmh\jmh-generator-annprocess\1.21\jmh-generator-annprocess-1.21.jar" org.openjdk.jmh.Main com.example.demo.jmh.PSTest.testForEach
# JMH version: 1.21
# VM version: JDK 1.8.0_171, Java HotSpot(TM) 64-Bit Server VM, 25.171-b11
# VM invoker: C:\Program Files\Java\jdk1.8.0_171\jre\bin\java.exe
# VM options: -Dfile.encoding=UTF-8
# Warmup: 5 iterations, 10 s each
# Measurement: 5 iterations, 10 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: com.example.demo.jmh.PSTest.testForEach# Run progress: 0.00% complete, ETA 00:08:20
# Fork: 1 of 5
# Warmup Iteration   1: 0.754 ops/s
# Warmup Iteration   2: 0.751 ops/s
# Warmup Iteration   3: 0.759 ops/s
# Warmup Iteration   4: 0.762 ops/s
# Warmup Iteration   5: 0.756 ops/s
Iteration   1: 0.754 ops/s
Iteration   2: 0.758 ops/s
Iteration   3: 0.760 ops/s
Iteration   4: 0.757 ops/s
Iteration   5: 0.751 ops/s# Run progress: 20.00% complete, ETA 00:07:06
# Fork: 2 of 5
# Warmup Iteration   1: 0.761 ops/s
# Warmup Iteration   2: 0.773 ops/s
# Warmup Iteration   3: 0.764 ops/s
# Warmup Iteration   4: 0.768 ops/s
# Warmup Iteration   5: 0.772 ops/s
Iteration   1: 0.775 ops/s
Iteration   2: 0.773 ops/s
Iteration   3: 0.760 ops/s
Iteration   4: 0.737 ops/s
Iteration   5: 0.748 ops/s# Run progress: 40.00% complete, ETA 00:05:18
# Fork: 3 of 5
# Warmup Iteration   1: 0.765 ops/s
# Warmup Iteration   2: 0.705 ops/s
# Warmup Iteration   3: 0.723 ops/s
# Warmup Iteration   4: 0.763 ops/s
# Warmup Iteration   5: 0.753 ops/s
Iteration   1: 0.751 ops/s
Iteration   2: 0.752 ops/s
Iteration   3: 0.759 ops/s
Iteration   4: 0.753 ops/s
Iteration   5: 0.761 ops/s# Run progress: 60.00% complete, ETA 00:03:33
# Fork: 4 of 5
# Warmup Iteration   1: 0.748 ops/s
# Warmup Iteration   2: 0.743 ops/s
# Warmup Iteration   3: 0.746 ops/s
# Warmup Iteration   4: 0.742 ops/s
# Warmup Iteration   5: 0.739 ops/s
Iteration   1: 0.744 ops/s
Iteration   2: 0.734 ops/s
Iteration   3: 0.739 ops/s
Iteration   4: 0.729 ops/s
Iteration   5: 0.749 ops/s# Run progress: 80.00% complete, ETA 00:01:47
# Fork: 5 of 5
# Warmup Iteration   1: 0.757 ops/s
# Warmup Iteration   2: 0.737 ops/s
# Warmup Iteration   3: 0.726 ops/s
# Warmup Iteration   4: 0.730 ops/s
# Warmup Iteration   5: 0.717 ops/s
Iteration   1: 0.720 ops/s
Iteration   2: 0.721 ops/s
Iteration   3: 0.737 ops/s
Iteration   4: 0.747 ops/s
Iteration   5: 0.714 ops/sResult "com.example.demo.jmh.PSTest.testForEach":0.747 ±(99.9%) 0.012 ops/s [Average](min, avg, max) = (0.714, 0.747, 0.775), stdev = 0.016CI (99.9%): [0.736, 0.759] (assumes normal distribution)# Run complete. Total time: 00:08:58REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on
why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial
experiments, perform baseline and negative tests that provide experimental control, make sure
the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts.
Do not assume the numbers tell you what you want them to tell.Benchmark            Mode  Cnt  Score   Error  Units
PSTest.testForEach  thrpt   25  0.747 ± 0.012  ops/sProcess finished with exit code 0

(二)JMH中的基本概念

  1. Warmup 预热,由于JVM中对于特定代码会存在优化(本地化),预热对于测试结果很重要

  2. Mesurement 总共执行多少次测试

  3. Timeout

  4. Threads 线程数,由fork指定

  5. Benchmark mode 基准测试的模式

  6. Benchmark 测试哪一段代码

二,Disruptor

(一)介绍

主页:LMAX Disruptor

源码:https://github.com/LMAX-Exchange/disruptor

GettingStarted: Getting Started · LMAX-Exchange/disruptor Wiki · GitHub

api: http://lmax-exchange.github.io/disruptor/docs/index.html

maven: https://mvnrepository.com/artifact/com.lmax/disruptor

一个线程中每秒处理600万订单,是金融机构开发的用于交易的。

2011年获得Duke奖项

单机速度最快的MQ

性能极高,无锁CAS,单机支持高并发

内存中用于存储的高效队列。

(二)Disruptor的特点

对比ConcurrentLinkedQueue : 链表实现

JDK中没有ConcurrentArrayQueue ,是因为数组是固定长度的,那么每次扩展都需要复制+1,效率低

Disruptor是数组实现的

数组是实现的ConcurrentArrayQueue 且头尾相连,

为什么效率比链表快,第一,链表没有数组遍历快;第二,链表需要维护头尾两个指针,数组只需维护一个sequence序列(下个元素的位置);

怎么计算加在环形数组的位置? 添加元素的第几个元素  /  数组容量   求余

无锁,高并发,使用环形Buffer,直接覆盖(不用清除)旧的数据,降低GC频率

实现了基于事件的生产者消费者模式(观察者模式)

(三)RingBuffer

环形队列

RingBuffer的序号,指向下一个可用的元素

采用数组实现,没有首尾指针

对比ConcurrentLinkedQueue,用数组实现的速度更快

假如长度为8,当添加到第12个元素的时候在哪个序号上呢?用12%8决定

当Buffer被填满的时候到底是覆盖还是等待,由Producer决定

长度设为2的n次幂,利于二进制计算,例如:12%8 = 12 & (8 - 1) pos = num & (size -1)

01:14“09

(四)Disruptor开发步骤

  1. 定义Event - 队列中需要处理的元素

  2. 定义Event工厂,用于填充队列

    这里牵扯到效率问题:disruptor初始化的时候,会调用Event工厂,对ringBuffer进行内存的提前分配

    GC产频率会降低

  3. 定义EventHandler(消费者),处理容器中的元素

1,事件发布模板

 long sequence = ringBuffer.next();  // Grab the next sequencetry {LongEvent event = ringBuffer.get(sequence); // Get the entry in the Disruptor// for the sequenceevent.set(8888L);  // Fill with data} finally {ringBuffer.publish(sequence);}

2,使用EventTranslator发布事件

 //===============================================================EventTranslator<LongEvent> translator1 = new EventTranslator<LongEvent>() {@Overridepublic void translateTo(LongEvent event, long sequence) {event.set(8888L);}};​ringBuffer.publishEvent(translator1);​//===============================================================EventTranslatorOneArg<LongEvent, Long> translator2 = new EventTranslatorOneArg<LongEvent, Long>() {@Overridepublic void translateTo(LongEvent event, long sequence, Long l) {event.set(l);}};​ringBuffer.publishEvent(translator2, 7777L);​//===============================================================EventTranslatorTwoArg<LongEvent, Long, Long> translator3 = new EventTranslatorTwoArg<LongEvent, Long, Long>() {@Overridepublic void translateTo(LongEvent event, long sequence, Long l1, Long l2) {event.set(l1 + l2);}};​ringBuffer.publishEvent(translator3, 10000L, 10000L);​//===============================================================EventTranslatorThreeArg<LongEvent, Long, Long, Long> translator4 = new EventTranslatorThreeArg<LongEvent, Long, Long, Long>() {@Overridepublic void translateTo(LongEvent event, long sequence, Long l1, Long l2, Long l3) {event.set(l1 + l2 + l3);}};​ringBuffer.publishEvent(translator4, 10000L, 10000L, 1000L);​//===============================================================EventTranslatorVararg<LongEvent> translator5 = new EventTranslatorVararg<LongEvent>() {​@Overridepublic void translateTo(LongEvent event, long sequence, Object... objects) {long result = 0;for(Object o : objects) {long l = (Long)o;result += l;}event.set(result);}};​ringBuffer.publishEvent(translator5, 10000L, 10000L, 10000L, 10000L);

3,使用Lamda表达式

 package com.mashibing.disruptor;​import com.lmax.disruptor.RingBuffer;import com.lmax.disruptor.dsl.Disruptor;import com.lmax.disruptor.util.DaemonThreadFactory;​public class Main03{public static void main(String[] args) throws Exception{// Specify the size of the ring buffer, must be power of 2.int bufferSize = 1024;​// Construct the DisruptorDisruptor<LongEvent> disruptor = new Disruptor<>(LongEvent::new, bufferSize, DaemonThreadFactory.INSTANCE);​// Connect the handlerdisruptor.handleEventsWith((event, sequence, endOfBatch) -> System.out.println("Event: " + event));​// Start the Disruptor, starts all threads runningdisruptor.start();​// Get the ring buffer from the Disruptor to be used for publishing.RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer();​​ringBuffer.publishEvent((event, sequence) -> event.set(10000L));​System.in.read();}}

4,ProducerType生产者线程模式

ProducerType有两种模式 Producer.MULTI和Producer.SINGLE

默认是MULTI,表示在多线程模式下产生sequence

如果确认是单线程生产者,那么可以指定SINGLE,效率会提升

如果是多个生产者(多线程),但模式指定为SINGLE,会出什么问题呢?

5,等待策略

如果来不及消费,会被覆盖怎么办?这就引出了等待策略

1,(常用)BlockingWaitStrategy:通过线程阻塞的方式,等待生产者唤醒,被唤醒后,再循环检查依赖的sequence是否已经消费。

2,BusySpinWaitStrategy:线程一直自旋等待,可能比较耗cpu

3,LiteBlockingWaitStrategy:线程阻塞等待生产者唤醒,与BlockingWaitStrategy相比,区别在signalNeeded.getAndSet,如果两个线程同时访问一个访问waitfor,一个访问signalAll时,可以减少lock加锁次数.

4,LiteTimeoutBlockingWaitStrategy:与LiteBlockingWaitStrategy相比,设置了阻塞时间,超过时间后抛异常。

5,PhasedBackoffWaitStrategy:根据时间参数和传入的等待策略来决定使用哪种等待策略

6,TimeoutBlockingWaitStrategy:相对于BlockingWaitStrategy来说,设置了等待时间,超过后抛异常

7,(常用)YieldingWaitStrategy:尝试100次,然后Thread.yield()让出cpu

8,(常用)SleepingWaitStrategy : sleep

6,消费者异常处理

默认:disruptor.setDefaultExceptionHandler()

覆盖:disruptor.handleExceptionFor().with()

7,依赖处理

    <!-- https://mvnrepository.com/artifact/com.lmax/disruptor --><dependency><groupId>com.lmax</groupId><artifactId>disruptor</artifactId><version>3.4.2</version></dependency>

多线程与高并发(六) 单机压测工具JMH,Disruptor原理解析相关推荐

  1. 多线程与高并发(九):单机压测工具JMH,单机最快MQ - Disruptor原理解析

    单机压测工具JMH JMH Java准测试工具套件 什么是JMH 官网 http://openjdk.java.net/projects/code-tools/jmh/ 创建JMH测试 1.创建Mav ...

  2. 不看我真的会很伤心【压测工具:提升系统性能的利器】,查看TPS,计算TPS,计算压测指标、压测名词解释、教大家如何压测

    目录 前言 一.压测是什么? 二.为什么要压测? 三. 压测名词解释 1.压测类型解释 2.压测名词解释 3.机器性能指标解释 4.访问指标解释 四.如何计算压测指标 五.常见的压测工具 1.JMet ...

  3. 基准测试工具(压测工具):wrk---高并发、损耗低,安装简单 (一)

    基准测试工具:Wrk初识   最近和同事聊起常用的一些压测工具,谈到了Apache ab.阿里云的PTS.Jmeter.Locust以及wrk各自的一些优缺点和适用的场景类型. 这篇博客,简单介绍下H ...

  4. 多线程导出excel高并发_大牛带你深入java多线程与高并发:JMH与Disruptor,确定能学会?...

    前言 今天我们讲两个内容,第一个是JMH,第二个是Disruptor.这两个内容是给大家做更进一步的这种多线程和高并发的一些专业上的处理.生产环境之中我们很可能不自己定义消息队列,而是使用 Disru ...

  5. 【腾讯优测干货分享】从压测工具谈并发、压力、吞吐量

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/580d914e07b7fc1c26a0cf7c 前言 随着部门业务的拓展,我们有 ...

  6. java多线程实例_多线程&高并发(全网最新:面试题+导图+笔记)面试手稳心不慌...

    前言 当你开始开始去跳槽面试的时候,明明只是一份15K的工作,却问你会不会多线程,懂不懂高并发,火箭造得让你猝及不防,结果就是凉凉:现如今市场,多线程.高并发编程.分布式.负载均衡.集群等可以说是现在 ...

  7. 多线程&高并发(全网最新:面试题 + 导图 + 核心学习笔记)面试手稳心不慌,轻松拿下 offer,秋招跳槽必不可少的底层能力

    前言 当你开始开始去跳槽面试的时候,明明只是一份 15K 的工作,却问你会不会多线程,懂不懂高并发,火箭造得让你猝及不防,结果就是凉凉:现如今市场,多线程.高并发编程.分布式.负载均衡.集群等可以说是 ...

  8. 多线程与高并发基础一(超发--多线程悲观锁,乐观锁、类数据库悲观锁乐观锁)

    PS:看完文章后对自己以前所做过的并发和锁机制有了深入原理的了解. 知其然和知其所以然! 遂以记之! 关键词: 线程,同步,单例,高并发,高访问,死锁 一.大规模并发带来的挑战 在过去的工作中,我曾经 ...

  9. 【Java】多线程与高并发

    多线程与高并发 synchronized 篇 进程 线程 协程/纤程(Quasur) 线程:一个程序里不同的执行路径 public static class T1 extends Thread{@Ov ...

最新文章

  1. 我来发美食啦,馋一下各位看官
  2. oracle_base,Oracle--基础知识--Oracle 数据库目录 ORACLE_BASE ORACLE_HOME
  3. Year-End Review
  4. CCF201912-1 报数
  5. 线程池中 corePoolSize, maximumPoolSize, poolSize理解
  6. python语言的官方网站-web2py
  7. 黑马程序员Java零基础视频教程(2022最新Java)B站视频学习笔记-Day6-方法
  8. 【赶紧收藏】平面设计必备字体,广告设计常用字体
  9. 快速计算网络地址和广播地址
  10. 单细胞文章专列——细胞图谱
  11. 3步教你如何做好技术入股
  12. Python深度学习笔记04——tensorflow实现神经网络(壹)
  13. XDOJ综合题 数字统计排序
  14. 《数字图像处理》学习总结及感悟:第二章数字图像基础(4)像素间的关系
  15. Word支持的正则表达式
  16. java将字符转换成拼音_java中将汉字转换成拼音的实现代码
  17. python中模块打补丁
  18. 双差法(HYPODD)定位软件安装教程2
  19. LeetCode(262):行程和用户 Trips and Users(SQL)
  20. VS code C/C++扩展包依赖cpptools-win32.vsix离线安装

热门文章

  1. vue3.0 知识点整理
  2. 整蛊朋友的python代码{1}(二次创作)
  3. ESD静电放电发生器测试报告样本
  4. android手机 运行java程序退出_手机为什么程序退出还在运行怎么办
  5. 计网复习题和知识点+最终版
  6. postgresql 序列Sequence
  7. java核心技术总结
  8. 开源啦!OMAP-L138/C6748 TI C6000 DSP/ARM 工业级核心板/口袋板/教学实验箱硬件设计开源
  9. 2021年江苏制造业百强企业排行榜:24家苏州企业营收比重达43.66%(附年榜TOP100详单)
  10. 实验6 在应用程序中播放音频和视频