玖叶教程网

前端编程开发入门

丰巢面试真题讲解系列-NO3

一.解决map的并发问题?案

HashMap不是线程安全的;Hashtable线程安全,但效率低,因为是Hashtable是使?synchronized的,所有线程竞争同?把锁;?ConcurrentHashMap不仅线程安全?且效率?,因为它包含?个segment数组,将数据分段存储,给每?段数据配?把锁,也就是所谓的锁分段技术。

解决Map的并发问题,通常有多种方案,以下是几种常见的解决方法:

  1. 使用Collections.synchronizedMap

Java的Collections工具类提供了一个静态方法synchronizedMap,它可以为普通的Map集合提供线程安全的访问。当多个线程需要并发地读写Map时,可以通过这个方法来获取一个线程安全的Map。但需要注意的是,即使使用了synchronizedMap,也需要在迭代时手动同步,否则可能会遇到并发修改异常。

  1. 使用ConcurrentHashMap

ConcurrentHashMap是Java集合框架中专门为并发设计的一个线程安全的哈希表实现。它内部采用分段锁机制,允许多个线程并发地读写Map,从而大大提高了并发性能。此外,ConcurrentHashMap还在JDK 1.8中引入了CAS操作和红黑树优化,进一步提升了性能。

  1. 使用锁:

对于自定义的Map实现或者第三方库提供的Map,可以通过显式地加锁来保证其线程安全性。可以使用synchronized关键字或者ReentrantLock等锁机制来同步对Map的访问。但需要注意的是,这种方法的性能可能不如ConcurrentHashMap,因为锁的粒度较大,容易导致线程之间的竞争。

  1. 使用读写锁:

对于读多写少的场景,可以使用读写锁(如ReadWriteLock)来优化性能。读写锁允许多个线程同时读取数据,但在写入数据时会阻塞其他所有线程。这样可以充分利用多核CPU的优势,提高并发性能。

  1. 使用并发集合框架的其他类:

Java并发集合框架还提供了其他并发安全的集合类,如CopyOnWriteArrayList、ConcurrentSkipListMap等。这些类也可以用来解决Map的并发问题,但需要根据具体场景和需求来选择。

在选择解决方案时,需要综合考虑并发性能、数据一致性、代码复杂度等因素。对于大多数场景来说,使用ConcurrentHashMap是一个很好的选择,因为它既提供了线程安全性,又具有较高的并发性能。

二.什么是协程,以及实现要点

1、?产者/消费者模式不是?性能的实现:

1.涉及到同步锁。

2.涉及到线程阻塞状态和可运?状态之间的切换。

3.涉及到线程上下?的切换。

2、协成定义:协程,英?Coroutines,是?种?线程更加轻量级的存在。正如?个进程可以拥有多个线程?样,?个线程也可以拥有多个协程。最重要的是,协程不是被操作系统内核所管理,?完全是由程序所控制(也就是在?户态执?)。

这样带来的好处就是性能得到了很?的提升,不会像线程切换那样消耗资源。

3、协成优点:协程的暂停完全由程序控制,线程的阻塞状态是由操作系统内核来进?切换。因此,协程的开销远远?于线程的开销。

4、实现:

1、Lua语?

Lua从5.0版本开始使?协程,通过扩展库coroutine来实现。

2、Python语?

正如刚才所写的代码示例,python可以通过 yield/send 的?式实现协程。在python 3.5以后, async/await 成为了更好的替代?案。

3、Go语?

Go语?对协程的实现?常强??简洁,可以轻松创建成百上千个协程并发执?。

4、Java语?

Java语?并没有对协程的原??持,但是某些开源框架模拟出了协程的功能

三.lru cache 使?hash map 的实现(算法)

1、概念:其实解释起来很简单,LRU就是Least Recently Used的缩写,翻译过来就是“最近最少使?”。也就是说LRU算法会将最近最少?的缓存移除,让给最新使?的缓存。?往往最常读取的,也就是读取次数最多的,所以利?好LRU算法,我们能够提供对热点数据的缓存效率,能够提?缓存服务的内存使?率。

2、实现:

1、思路:

i. 限制缓存??

ii. 查询出最近最晚?的缓存

iii. 给最近最少?的缓存做?个标识

2、代码:

1 import java.util.LinkedHashMap;
2 import java.util.Map;
3 /**
4 * 简单?LinkedHashMap来实现的LRU算法的缓存
5 */
6 public class LRUCache<K, V> extends LinkedHashMap<K, V> {
7 private int cacheSize;
8 public LRUCache(int cacheSize) {
9 super(16, (float) 0.75, true);
10 this.cacheSize = cacheSize;
11 }
12 protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
13 return size() > cacheSize;
14 }
15 }

四.基本排序(算法)

1. 快速排序:

a. 原理:快速排序采?的是?种分治的思想,它先找?个基准数,然后将?这个基准数?的数字都放到它的左边,然后再递归调?,分别对左右两边快速排序,直到每?边只有?个数字.整个排序就完成了.

b. 复杂度:O(n)

c. 特点:快速排序是我们平常最常使?的?种排序算法,因为它速度快,效率?,是最优秀的?种排序算法.

2. 冒泡排序:

a. 原理:冒泡排序其实就是逐??较交换,进??外两次循环,外层循环为遍历所有数字,逐个确定每个位置,?层循环为确定了位置后,遍历所有后?没有确定位置的数字,与该位置的数字进??较,只要?该位置的数字?,就和该位置的数字进?交换.

b. 复杂度:O(n^2),最佳时间复杂度为O(n)

c. 特点:冒泡排序在我们实际开发中,使?的还是?较少的.它更加适合数据规模?较少的时候,因为它的效率是?较低的,但是优点是逻辑简单,容易让我们记得.

3. 直接插?排序:

a. 原理:直接插?排序是将从第?个数字开始,逐个拿出来,插?到之前排好序的数列?.

b. 复杂度:O(n^2),最佳时间复杂度为O(n)

c. 特点:

4. 直接选择排序:

a. 原理:直接选择排序是从第?个位置开始遍历位置,找到剩余未排序的数据?最?的,找到最?的后,再做交换

b. 复杂度:O(n^2)

c. 特点:和冒泡排序?样,逻辑简单,但是效率不?,适合少量的数据排序

五.说说b+树?

1. B-tree:



B-tree 利?了磁盘块的特性进?构建的树。每个磁盘块?个节点,每个节点包含了很关键字。把树的节点关键字增多后树的层级?原来的?叉树少了,减少数据查找的次数和复杂度。

B-tree巧妙利?了磁盘预读原理,将?个节点的??设为等于?个?(每?为4K),这样每个节点只需要?次I/O就可以完全载?。

B-tree 的数据可以存在任何节点中。

2. B+tree:



B+tree 是 B-tree 的变种,B+tree 数据只存储在叶?节点中。这样在B树的基础上每个节点存储的关键字数更多,树的层级更少所以查询数据更快,所有指关键字指针都存在叶?节点,所以每次查找的次数都相同所以查询速度更稳定;

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言