分布式事务
- 主流的关系型数据库产品都是实现了XA接口,事务管理器和资源管理器之间使用XA协议,JTA(Java Transaction API)。
TCC
try comfirm cancel 。本地消息表
采用定时轮询扫描的方式,去检查消息表的数据。消息队列
采用时效性高的MQ,由对方订阅消息并监听,有消息时自动触发事件。
1)CountDownLatch
(闭锁) 是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待
2)CyclicBarrier
(栅栏) 之所以叫barrier,是因为是一个同步辅助类,允许一组线程互相等待,直到到达某个公共屏障点 ,并且在释放等待线程后可以重用。
3)Semaphore
(信号量) 是一个计数信号量,它的本质是一个“共享锁“。信号量维护了一个信号量许可集。线程可以通过调用 acquire()来获取信号量的许可;当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待, 直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可。
1)ScheduledExecutorService
解决那些需要任务重复执行的问题
2)ScheduledThreadPoolExecutor
周期性任务调度的类实现
包含有AtomicBoolean、AtomicInteger、AtomicIntegerArray等原子变量类,他们的实现原理大多是持有它们各自的对应的类型变量value,而且被volatile关键字修饰了。这样来保证每次一个线程要使用它都会拿到最新的值。
1)ReentrantLock
它是独占锁,是指只能被独自占领,即同一个时间点只能被一个线程锁获取到的锁。
2)ReentrantReadWriteLock
它包括子类ReadLock和WriteLock。ReadLock是共享锁,而WriteLock是独占锁。
3)LockSupport
它具备阻塞线程和解除阻塞线程的功能,并且不会引发死锁。
1)ArrayList对应的高并发类是CopyOnWriteArrayList,
2)HashSet对应的高并发类是 CopyOnWriteArraySet,
3)HashMap对应的高并发类是ConcurrentHashMap等等
答:首先,我们要明白hashCode()和equals()方法的作用是什么,然后才能说他的区别,说了区别之后在说明使用的时候需要注意的地方,这样的回答思路基本是OK的。
一、hahsCode()和equals()的作用是什么?
hahsCode()和equals()的作用其实是一样的,目的都是为了比较两个对象是否相等一致
二、hahsCode()和equals()的区别是什么?
我们可以从两个角度分别介绍他们的区别:一个是性能,一个是可靠性。他们的主要区别体现在这里
1.equals()既然已经实现比较两个对象的功能了,为什么还需要hashCode()呢?
因为重写的equals()里一般比较的较为全面和复杂(它会对这个对象内所以成员变量一一进行比较),这样效率很低,而通过hashCode()对比,则只要生成一个hash值就能比较了,效率很高
因为hashCode()并不是完全可靠,非常有可能的情况是,两个完全不同的对象的hash值却是一样的。
所以会有下面三个重要的结论:
1.NameServer
可以理解为是消息队列的协调者,Broker向它注册路由信息,同时Client向其获取路由信息,如果使用过Zookeeper,就比较容易理解了,但是功能比Zookeeper弱;
NameServer本身是没有状态的,并且多个NameServer直接并没有通信,可以横向扩展多台,Broker会和每一台NameServer建立长连接;
2.Broker
Broker是RocketMQ的核心,提供了消息的接收,存储,拉取等功能,一般都需要保证Broker的高可用,所以会配置Broker Slave,当Master挂掉之后,Consumer然后可以消费Slave;
Broker分为Master和Slave,一个Master可以对应多个Slave,Master与Slave的对应关系通过指定相同的BrokerName,不同的BrokerId来定义,BrokerId为0表示Master,非0表示Slave;
3.Producer
消息队列的生产者,需要与NameServer建立连接,从NameServer获取Topic路由信息,并向提供Topic服务的Broker Master建立连接;Producer无状态,看集群部署;
4.Consumer
消息队列的消费者,同样与NameServer建立连接,从NameServer获取Topic路由信息,并向提供Topic服务的Broker Master,Slave建立连接;
5.Topic和Message Queue
在介绍完以上4个角色以后,还需要重点介绍一下上面提到的Topic和Message Queue;字面意思就是主题,用来区分不同类型的消息,发送和接收消息前都需要先创建Topic,针对Topic来发送和接收消息,为了提高性能和吞吐量,引入了Message Queue,一个Topic可以设置一个或多个Message Queue,有点类似kafka的分区(Partition),这样消息就可以并行往各个Message Queue发送消息,消费者也可以并行的从多个Message Queue读取消息;
2.1 LocalDateTime 转 时间戳
1 | //方式一 |
2.2 时间戳 转LocalDateTime
以下几种获取的LocalDateTime方式按读者需求进行获取,不同的精确值,将获取不同的结果;
1 |
|
原先的Date and Calendar 类的api比较复杂,不易于理解,应用起来不是很灵活。
Calendar 是个线程不安全的类会导致SimpleDateFormat线程不安全。
java.time是JSR 310: Date and Time API.规范所开发,其所有类都是线程安全的或者是枚举类型的类
java.time 的API 使用简单,能够灵活计算时间,矫正时间。
LocalDate 是 日期,在java.time 中 日期和时间是可以分开和组合的。
2.1 创建date的方式
// 创建date的方式
1 | public void LocalDateTest(){ |
2.2 使用LocalDate读取date
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86List<People> list = new ArrayList<>();
//取前20个
list=list.stream().limit(20).collect(Collectors.toList());
//取属性
List<String> spuCodes = list.stream().map(People::getName).collect(Collectors.toList());
//拼接
List<Integer> numbers = ImmutableList.of(1, 2, 3, 4, 5);
String result = numbers.stream().map(Object::toString).collect(Collectors.joining(","));
String result = numbers.stream().collect(Collectors.joining(", ", "[", "]"));
//根据age对list分组 List<X> -> map<x.id,List<x>>
Map<String,List<People>> groupByAge = list.stream().collect(Collectors.groupingBy(People::getAge));
//根据age对list的属性分组 List<X> -> map<x.id,List<x.name>>
Map<Long,List<String>> exhibitionPitemMap = list.stream().collect(
Collectors.groupingBy(People::getLong, Collectors.mapping(People::getName, Collectors.toList())));
//根据age进行排序(reserve倒序)
List<People> peopleListSorted = list.stream().sorted(Comparator.comparing(People::getAge)
.reversed()).collect(Collectors.toList());
//提取age,并排序
List<String> ageList = list.stream().map(People::getAge).distinct().sorted().collect(Collectors.toList());
//提取年龄大于20的people
List<People> olderThan20 = list.stream().filter(e->Integer.parseInt(e.getAge()) > 20)
.collect(Collectors.toList());
//累加
BigDecimal totalMoney = list.stream().map(People::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
list.stream().mapToLong(People::getAge).sum();
Long sum2 = list.stream().reduce(0L, Long::sum);
//过滤取单个值
People people = list.stream().filter(e->e.getAge().equals("20")).findFirst().orElse(null);
//查找流中最大值和最小值
List<Person> personList = generatePersonList();
Person olderOne = personList.stream().max(Comparator.comparing(Person::getAge)).orElse(null);
Person youngerOne = personList.stream().min(Comparator.comparing(Person::getAge)).orElse(null);
//对象去重
ArrayList<Person> collect = personList.stream().collect(Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(Comparator.comparingInt(Person::getAge))),
ArrayList::new));
//转换成String[]
list..stream().toArray(String[]::new)
//拼接字符串
request.getModuleIdList().stream().map(x-> x.toString()).collect(Collectors.joining(","));
// List<x> -> Map<x.id,x>
//1,key存在重复时,会抛出异常
Map<Long, Person> id2Entity = personList.stream().collect(Collectors.toMap(Person::getId, x-> x));
//2,解决key重复异常情况
Map<Long, Person> entityMap= personList.stream().collect(Collectors.toMap(Person::getId, Function.identity(),(x,y) -> y));
//list 分割
int pageNum = (list.size()+ PAGE_SIZE -1) / PAGE_SIZE;
List<List<Long>> splitList = Stream.iterate(0, n->n+1).limit(pageNum).parallel()
.map(a-> list.stream().skip(a*PAGE_SIZE).limit(PAGE_SIZE).parallel().collect(Collectors.toList())).collect(Collectors.toList());