Java并发编程:volatile关键字解析 https://www.cnblogs.com/dolphin0520/p/3920373.html
什么是CAS机制? https://blog.csdn.net/qq_32998153/article/details/79529704
--ConcurrentHashMap1.7使用lock锁实现,1.8使用cas+synchronized ,更多应用见atomic包
分布式锁 https://blog.csdn.net/q975583865/article/details/78375160
nohup java -Xms512m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m -Dfile.encoding=UTF8 -Djava.io.tmpdir=tmp -jar stec-szmis-service.jar --management.port=5220 --management.security.enabled=false --management.address=127.0.0.1 --tid F3BC9F237DBD9DBF4D033DB5B9A09EA6>/dev/null 2>&1 &
kill -9 `ps -ef|grep F3BC9F237DBD9DBF4D033DB5B9A09EA6|grep -v grep|awk '{print $2}'`
list 多条件排序
List
1.不能用stop,要用 thread.interrupt();
2.使用状态标识+volatile
1.都必须写在同步代码块中,wait会释放锁
2.wait必须在notify之后执行,否则可能死锁
与wait 不同,与unpark没有顺序要求,但是park不会释放锁!
必须在同步代码块中使用while来判断线程是否进入等待状态,if可能有伪唤醒(JDK原因)
hashtable:synchronized,导致读锁之间的互斥,只有一个线程能读
concurrentmap:ReentrantReadWriteLock,读与读之间能并发
分解任务fork出新任务,聚集join任务结果
ForkJoinTask子类
RecursiveTask (可返回结果)或 RecursiveAction
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.concurrent.*;
/**
* 并行调用http接口
*/
@Service
public class UserServiceForkJoin {
// 本质是一个线程池,默认的线程数量:CPU的核数
ForkJoinPool forkJoinPool = new ForkJoinPool(10, ForkJoinPool.defaultForkJoinWorkerThreadFactory,
null, true);
@Autowired
private RestTemplate restTemplate;
/**
* 查询多个系统的数据,合并返回
*/
public Object getUserInfo(String userId) throws ExecutionException, InterruptedException {
// 其他例子, 查数据库的多个表数据,分多次查询
// fork/join
// forkJoinPool.submit()
ArrayList urls = new ArrayList<>();
urls.add("http://www.tony.com/userinfo-api/get?userId=" + userId);
urls.add("http://www.tony.com/integral-api/get?userId=" + userId);
HttpJsonRequest httpJsonRequest = new HttpJsonRequest(restTemplate, urls, 0, urls.size() - 1);
ForkJoinTask forkJoinTask = forkJoinPool.submit(httpJsonRequest);
JSONObject result = forkJoinTask.get();
return result;
}
}
// 任务
class HttpJsonRequest extends RecursiveTask {
RestTemplate restTemplate;
ArrayList urls;
int start;
int end;
HttpJsonRequest(RestTemplate restTemplate, ArrayList urls, int start, int end) {
this.restTemplate = restTemplate;
this.urls = urls;
this.start = start;
this.end = end;
}
// 就是实际去执行的一个方法入口(任务拆分)
@Override
protected JSONObject compute() {
int count = end - start; // 代表当前这个task需要处理多少数据
// 自行根据业务场景去判断是否是大任务,是否需要拆分
if (count == 0) {
String url = urls.get(start);
// TODO 如果只有一个接口调用,立刻调用
long userinfoTime = System.currentTimeMillis();
String response = restTemplate.getForObject(url, String.class);
JSONObject value = JSONObject.parseObject(response);
System.out.println(Thread.currentThread() + " 接口调用完毕" + (System.currentTimeMillis() - userinfoTime) + " #" + url);
return value;
} else { // 如果是多个接口调用,拆分成子任务 7,8, 9,10
System.out.println(Thread.currentThread() + "任务拆分一次");
int x = (start + end) / 2;
HttpJsonRequest httpJsonRequest = new HttpJsonRequest(restTemplate, urls, start, x);// 负责处理哪一部分?
httpJsonRequest.fork();
HttpJsonRequest httpJsonRequest1 = new HttpJsonRequest(restTemplate, urls, x + 1, end);// 负责处理哪一部分?
httpJsonRequest1.fork();
// join获取处理结果
JSONObject result = new JSONObject();
result.putAll(httpJsonRequest.join());
result.putAll(httpJsonRequest1.join());
return result;
}
}
}
@Autowired
UserServiceForkJoin userServiceForkJoin;
@controller
public void testUserSerivce() throws Exception {
// 调用
long currentTimeMillis = System.currentTimeMillis();
// http 实际就是 线程 调用service
Object userInfo = userServiceForkJoin.getUserInfo("tony");
System.out.println("getUserInfo总执行时间为" + (System.currentTimeMillis() - currentTimeMillis));
System.out.println(userInfo.toString());
}
ExecutorService executorService = Executors.newCachedThreadPool();
/**
* 查询多个系统的数据,合并返回
*/
public Object getUserInfo(String userId) throws InterruptedException {
CountDownLatch count = new CountDownLatch(2);
ArrayList values = new ArrayList<>();
// 你可以封装成一个 提交URL 就能自动多线程调用的 工具
executorService.submit(() -> {
// 1. 先从调用获取用户基础信息的http接口
long userinfoTime = System.currentTimeMillis();
String value = restTemplate.getForObject("http://www.tony.com/userinfo-api/get?userId=" + userId, String.class);
JSONObject userInfo = JSONObject.parseObject(value);
System.out.println("userinfo-api用户基本信息接口调用时间为" + (System.currentTimeMillis() - userinfoTime));
values.add(userInfo);
count.countDown();
});
executorService.submit(() -> {
// 2. 再调用获取用户积分信息的接口
long integralApiTime = System.currentTimeMillis();
String intergral = restTemplate.getForObject("http://www.tony.com/integral-api/get?userId=" + userId,
String.class);
JSONObject intergralInfo = JSONObject.parseObject(intergral);
System.out.println("integral-api积分接口调用时间为" + (System.currentTimeMillis() - integralApiTime));
values.add(intergralInfo);
count.countDown();
});
count.await();// 等待计数器归零
// 3. 合并为一个json对象
JSONObject result = new JSONObject();
for (JSONObject value : values) {
result.putAll(value);
}
return result;
}
https://blog.csdn.net/q975583865/article/details/84951656
三大核心部分: Channel(通道), Buffer(缓冲区), Selector
NIO 基于 Channel 和 Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中 。Selector(选择区)用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个线程可以监听多个数据通道。
BIO 是面向流的, NIO 是面向缓冲区的
是一个高性能、异步事件驱动的 NIO 框架
Reactor线程模型,定义了accept线程组和io线程组,将通道注册到accept线程的selector上,io线程监听事件
channel,负责socket连接和数据的处理,写入buffer
channelPipeline职责链设计模式,事件处理机制
ByteBuf缓冲区,传输数据
如果ChannelHandler被注解为 @Sharable,全局只有一个handler实例,它会被多个Channel的Pipeline共享,会被多线程并发调用,因此它不是线程安全的;如果存在跨ChannelHandler的实例级变量共享,需要特别注意,它可能不是线程安全的。
总之,只应该在确定了你的 ChannelHandler 是线程安全的时才使用@Sharable 注解
server = new ServerBootstrap();
server.group(bossGroup, workerGroup)
.childOption(ChannelOption.SO_RCVBUF,32*1024)
.childOption(ChannelOption.SO_SNDBUF,32*1024)
再定义一个 处理数据的线程池bizGroup(操作数据库等)
private EventLoopGroup bossGroup; // 主线程池,处理连接的线程池
private EventLoopGroup workerGroup; // 工作线程池,处理io的线程池
private EventLoopGroup bizGroup; // 业务线程池,处理数据的线程池
bizGroup = new NioEventLoopGroup(20,new DefaultThreadFactory("biz-thread-pool-")); //根据需要10,200 。。。
// 添加自定义的handler
pipeline.addLast(bizGroup,new ChatHandler());
在责任链的最后一个Handler
// 添加自定义的handler
pipeline.addLast(new ChatHandler());
里添加
ctx.fireChannelRead(msg);
(如果使用的SimpleChannelInboundHandler,它会自动进行释放)
1.消息顺序性
分为 生产者顺序发送 和 消费者顺序消费
2.有序消息的缺陷
未提交读(read uncommitted)、已提交读(read committed)、可重复读(repeatable read)、串行化(serializable)。
未提交读 A事务已执行,但未提交;B事务查询到A事务的更新后数据;A事务回滚;---出现脏数据
已提交读 (解决了脏读) A事务执行更新;B事务查询;A事务又执行更新;B事务再次查询时,前后两次数据不一致;---不可重复读
可重复读 (解决了不可重复读) A事务无论执行多少次,只要不提交,B事务查询值都不变;B事务仅查询B事务开始时那一瞬间的数据快照;
串行化 (解决了幻读) 不允许读写并发操作,写执行时,读必须等待;
脏读:指一个线程中的事务读取到了另外一个线程中未提交的数据。
不可重复读(虚读):指一个线程中的事务读取到了另外一个线程中提交的update的数据。
幻读:指一个线程中的事务读取到了另外一个线程中提交的insert的数据。
待更~
实现Comparable
接口,并重写接口中的compareTo方法
可一边遍历一遍删除,并发安全
加载,验证,准备,解析,初始化
当一个类收到了类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委派给父 类去完成 。
保证了使用不同的类加载器最终得到的都是同样一个 Object 对象
1.ACP理论放弃A,CP组合最终一致性,数据库操作和发送消息绑定
2.rocketmq自带的解决方案,提取出事务管理器,个人感觉像tcc