Spring并发线程竞争
@RestController
public class HelloWorldController {
//高并发下多个线程修改进程中的变量
static Integer num = 0;
@RequestMapping("/stat")
public Integer stat() {
return num;
}
@RequestMapping("/add")
public Integer add() {
return num++;
}
}
发100并发发一万次
ab -n 10000 -c 100 http://localhost:8080/add


使用node.js 压测
const http = require('http');
const hostname = '127.0.0.1';
const port = 8080;
var num = 0;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
if (req.url === "/stat") {
res.end(num +"");
} else if ((req.url === "/add")) {
num = num + 1;
res.end(num +"");
} else {
res.end('Hello World');
}
});
server.listen(port, hostname, () => {
console.log(`Server running at http://``{hostname}:``{port}/`);
});
因为node.js是单线程压测出来的结果是正确✅的
用锁变巨慢很危险
@RestController
public class HelloWorldController {
static Integer num = 0;
synchronized void __add() throws InterruptedException {
Thread.sleep(100);//模拟数据库io耗时
num++;
}
@RequestMapping("/stat")
public Integer stat() {
return num;
}
@RequestMapping("/add")
public Integer add() throws InterruptedException {
__add();
return 1;
}
}
##用 ThreadLocal改造
@RestController
public class HelloWorldController {
static ThreadLocal<Integer> num =
new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0;
}
};
void __add() throws InterruptedException {
Thread.sleep(100);
int sum = num.get() + 1;
num.set(sum);
}
@RequestMapping("/stat")
public Integer stat() {
return num.get();
}
@RequestMapping("/add")
public Integer add() throws InterruptedException {
__add();
return 1;
}
}

你会发现每个值分散在很多线程ThreadLocal中,怎么把所有线程计算结果收集起来?
class Var<T> {
T v;
public void set(T value) {
v = value;
}
public T get() {
return v;
}
}
@RestController
public class HelloWorldController {
// Integer 是值类型必须传引用类型
// static HashMap<String, Integer> map = new HashMap<>();
public static Set<Var<Integer>> set = new HashSet<>();
static ThreadLocal<Var<Integer>> varThreadLocal =
new ThreadLocal<Var<Integer>>() {
@Override
protected Var<Integer> initialValue() {
Var<Integer> v = new Var<>();
v.set(0);
addSet(v);//这里存在临界区所有要加锁
return v;
}
};
static synchronized void addSet(Var<Integer> v) {
set.add(v);
}
void __add() throws InterruptedException {
Thread.sleep(100);
Var<Integer> integerVar = varThreadLocal.get();
integerVar.set(integerVar.get() + 1);
}
@RequestMapping("/stat")
public Integer stat() {
if (set.isEmpty()) {
return 0;
}
return set.stream().filter(Objects::nonNull).map(x -> x.get()).reduce((a, x) -> a + x).get();
}
@RequestMapping("/add")
public Integer add() throws InterruptedException {
__add();
return 1;
}
