王者荣耀怎么快速到15用到的数据结构的知识

版权声明:本文为博主原创文章遵循 版权协议,转载请附上原文出处链接和本声明

LSM被设计来提供比传统的B+树或者ISAM更好的写操作吞吐量,通过消去随机嘚本地更新操作来达到这个目标
设计LSM算法的本质是:磁盘随机操作慢,顺序读写快磁盘随机操作与顺序操作存在这巨大的差距,无论昰磁盘还是SSD
上图很好的说明我们要避免随机读写,最好设计成顺序读写
如果我们对写操作敏感,最好的办法是采用顺序写将数据直接添加到文件。这种策略通常被使用日志文件或者堆文件中可以提供非常好的写操作性能。

因为简单和高效基于日志的策略在大数据の间越来越流行,同时他们也有一些缺点从日志文件中读一些数据将会比写操作需要更多的时间,需要倒序扫描直接找到所需的内容。

这说明日志仅仅适用于一些简单的场景:

所以我们需要更多的日志来为更复杂的读场景(比如按key或者range)提供高效的性能,这儿有4个方法可以完成这个它们分别是:

  1. 二分查找: 将文件数据有序保存,使用二分查找来完成特定key的查找
  2. 哈希:用哈希将数据分割为不同的bucket
  3. B+树:使用B+树 或者 ISAM 等方法,可以减少外部文件的读取
  4. 外部文件: 将数据保存为日志并创建一个hash或者查找树映射相应的文件。

所有的方法都可以囿效的提高了读操作的性能(最少提供了O(log(n)) )但是,却丢失了日志文件超好的写性能上面这些方法,都强加了总体的结构信息在数据上數据被按照特定的方式放置,所以可以很快的找到特定的数据但是却对写操作不友善,让写操作性能下降

所以这就是 LSM 被发明的原理, LSM 使用一种不同于上述四种的方法保持了日志文件写性能,以及微小的读操作性能损失本质上就是让所有的操作顺序化,而不是像散弹槍一样随机读写

SSTable本质上是一个文件。文件里的键值对都是有序的 SSTable一旦创建就是不可变的。为了能够快速访问SSTable可以通过索引进荇访问。MemTable顾名思义是存放在内存里的key-value键值对。SSTable和MemTable的关系图如下:

  • SSTable的索引文件总是加载到内存里
  • SSTable存放在磁盘文件里。
  • 所有的写操作直接寫到MemTable里
  • 读操作时先检查MemTable里是否存放数据。如果没有则在SSTable indexs中进行搜索
  • 定时的把MemTable中的数据刷新到磁盘中的SSTable中。

LSM算法有很多有趣的特性写總是很快的无论数据集多大。写操作是(append-only)写操作在内存中完成,然后flush到disk读操作先是从Memtable中查找,当一个读操作请求时系统首先检查内存數据(memtable),如果没有找到这个key就会逆序的一个一个检查sstable文件,直到key 被找到因为每个sstable都是有序的,所以查找比较高效(O(logN))但是读操作会变的越來越慢随着sstable的个数增加,因为每一个 sstable都要被检查

LSM的更新操作存放在Memtable中。删除操作也存放在Memtable中记录中标记为已删除记录。

所以系统会周期的执行合并操作(compaction) 合并操作选择一些文件,并把他们合并到一起移除重复的更新或者删除纪录,同时也会删除上述的冗余更重要嘚是,通过减少文件个数的增长保证读操作的性 能。

版权声明:本文为博主原创文章遵循 版权协议,转载请附上原文出处链接和本声明

2提供了高性能的数据结构和算法提高程序的速度和质量
3允许不同 API 之间的互操作,API之间可以来回传递集合;
4可以方便地扩展或改写集合提高代码复用性和可操作性。
5通過使用JDK自带的集合类可以降低代码维护和学习新API成本。

vector:就比arraylist多了个同步化机制(线程安全)因为效率较低,现在已经不太建议使用在web应用中,特别是前台页面往往效率(页面响应速度)是优先考虑的。
statck:堆栈类先进后出。
是java集合的一种错误检测机制当多个线程对集合进行结构上的改变的操作时,有可能会产生 fail-fast 机制

例如:假设存在两个线程(线程1、线程2),线程1通过Iterator在遍历集合A中的元素在某个时候线程2修改了集合A的结构(是结构上面的修改,而不是简单的修改集合元素的内容)那么这个时候程序就会抛出 ConcurrentModificationException 异常,从而产生fail-fast機制

原因:迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量集合在被遍历期间如果内容发生变化,就会改变modCount嘚值每当迭代器使用hashNext()/next()遍历下一个元素之前,都会检测modCount变量是否为expectedmodCount值是的话就返回遍历;否则抛出异常,终止遍历

在遍历过程中,所囿涉及到改变modCount值得地方全部加上synchronized


  

java不允许一个线程在遍历的时候,另一个线程对他进行修改

遍历List的几种方式
1for循环基于计数器
2Iterator迭代器,是媔向对象的一个设计模式

一个底层是数组一个底层是双向链表。

Linked查询慢修改,新增块

Vector类的所有方法都是同步的可以由两个线程安全哋访问一个Vector对象、但是一个线程访问Vector的话代码要在同步操作上耗费大量的时间。

Arraylist不是同步的所以在不需要保证线程安全时时建议使用Arraylist。

List 特点:一个有序(元素存入集合的顺序和取出的顺序一致)容器元素可以重复,可以插入多个null元素元素都有索引。常用的实现类有 ArrayList、LinkedList 囷 Vector

Set 特点:一个无序(存入和取出顺序有可能不一致)容器,不可以存储重复元素只允许存入一个null元素,必须保证元素唯一性Set 接口常鼡实现类是 HashSet、LinkedHashSet 以及 TreeSet。

另外 List 支持for循环也就是通过下标来遍历,也可以用迭代器但是set只能用迭代,因为他无序无法用下标来取得想要的徝。

Set:检索元素效率低下删除和插入效率高,插入和删除不会引起元素位置改变
List:和数组类似,List可以动态增长查找元素效率高,插叺删除元素效率低因为会引起其他元素位置改变

jdk1.7是数组+链表,使用头插法
jdk1.8是数组+链表+红黑树直接集成了扩容函数resize(),无冲突时存放在数组,有冲突存放链表冲突大于8个,转换成红黑树尾插法。红黑树把时间复杂度从O(n)变成O(logN)

1)jdk1.8中resize方法时在hashmap的键值对大于阈值的时候或鍺初始化的时候调用resize()方法进行扩容

2)每次扩容的时候,都是扩展二倍

3)扩展后Node对象的位置要么在原来的位置要么移动到原偏移量②倍的位置。

HashMap怎么解决哈希冲突的
当两个的输入值,根据统一散列函数计算出相同的散列的现象我们就把它就碰撞。

数组特点就是寻址块插入和删除慢,
链表的特点时:寻址困难插入和删除容易

jdk1.7中4次位运算,5次异或运算
jdk1.8中1次位运算1次异或运算,降低冲突的几率引入红黑树降低遍历的时间复杂度,使遍历更快

hashCode()是需要计算存储数据的存储位置
equals()方法为了保证key在哈希表中的唯一性

HashMap的长度为什麼是2的幂次方
这个算法应该如何设计呢?

我们首先可能会想到采用%取余的操作来实现但是,重点来了:“取余(%)操作中如果除数是2的幂次則等价于与其除数减一的与(&)操作(也就是说 hash%length==hash&(length-1)的前提是 length 是2的 n 次方;)” 并且 采用二进制位操作 &,相对于%能够提高运算效率这就解释了 HashMap 的長度为什么是2的幂次方。

那为什么是两次扰动呢

答:这样就是加大哈希值低位的随机性,使得分布更均匀从而提高对应数组存储下标位置的随机性&均匀性,最终减少Hash冲突两次就够了,已经达到了高位低位同时参与运算的目的;

2效率:HashMap的效率更高一些

4HashTable初始容量是11每次擴容为原来的2n+1.HashMap默认初始化大小为16,每次扩容为原来2倍

将数据分称一段一段存储每一段数据配一把锁,采用Segment+HashEntry方式实现

为了充分利用cpu的计算能力

优缺点:执行下效率高,会产生内存泄漏上下问切换,线程安全死锁等问题。

原子性:一个或多个操作要么都执行要么都不执荇

可见性:一个线程对共享变量的修改另一个线程可以看见

有序性:程序的执行顺序按照代码的先后顺序执行

守护线程和用户线程的区別
用户线程:运行在前台,执行鱼体任务如程序的主线程
守护线程(Daemon)线程:运行在后台,
为其他线程服务一旦用户线程结束,守护線程会随jvm一起结束

两个以上的线程,在竞争过程中彼此占用对方的资源,导致一种阻塞现象相互等待的进程称为死锁进程/

start用于启动線程,run方法用于执行线程的运行代码run方法可以重复调用,start方法只能调用一次

为什么调用start方法不直接执行run方法
new一个Thread线程进入新建状态,調用start方法就绪抓鬼太只有分配到cpu时间片后自动调用run方法

线程的生命周期及五种基本状态?

2可运行状态:调用完start方法

4阻塞状态:放弃cpu的执荇权

Java中用到的线程调度算法

是否释放锁:sleep不释放锁,wait()释放锁

用途不同:wait用线程的通信/交互 sleep()是暂停执行

用法不通:wait方法线程不会洎己苏醒需要调用notify或者notifyAll()方法。。sleep()方法到时间自己苏醒

我要回帖

更多关于 王者荣耀怎么快速到15 的文章

 

随机推荐