贝壳专题(1)

1: 有10条线程,需要同时开始执行,自己知道的做法全部说出来 :

自己想到的只是用一个10核的CPU电脑;

2:nio相关?

NIO的全称是New I/O,与之相对应的是Java中传统的I/O,这里都指的是Java的API包。

a:
传统的IO包提供的是同步阻塞IO,即当用户线程发出IO请求后,内核会去查看数据是否已经就绪,若未就绪,则用户线程会处于阻塞状态(让出CPU),当数据就绪后,内核会将数据复制到用户线程,并把结果返回给用户线程,同时接触用户线程的阻塞,同步体现在用户线程需要等待数据就绪后才能向后执行(后面的执行依赖于前面的结果)。服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,线程数量也会受到。

而NIO包提供的IO是同步非阻塞IO,非阻塞体现在用户线程发起IO请求后,会直接得到返回结果,即便在数据未就绪的情况下,也能马上得到失败信息。而同步体现在用户线程需要主动去轮询直到发现数据就绪,再主动将数据从内核拷贝到用户线程。服务器实现模式为多个连接一个线程(IO多路复用),即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。
在这里插入图片描述
b:NIO包API的用法。(1)Channel:Java NIO中的所有I/O操作都基于Channel对象,一个Channel(通道)代表和某一实体的连接,这个实体可以是文件、网络套接字等。也就是说,通道是Java NIO提供的一座桥梁,用于我们的程序和操作系统底层I/O服务进行交互。FileChannel:文件通道,从输入流输出流中获取实例,常见的使用场景就是从一个文件拷贝其内容到另一个文件。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3手撕TOP-K快排算法

分析:有多种方案可以实现。
一、最容易想到的是先对数据快速排序,然后输出前k个数字。
二、先定义容量为k的数组,从源数据中取出前k个填充此数组,调整此数组的最大值maxValue到首位,然后对剩下的n-k个数据迭代,对于每个遍历到的数字x,如果x < maxValue,用x把maxValue替换掉,然后调整数组最大值的位置。
三、基于二的思路,维护容量为k的堆,从源数据中取出前k个填充实例化堆,调整此堆中的最大值maxValue到堆顶,然后对剩下的n-k个数据迭代,对于每个遍历到的数字x,如果x < maxValue,用x把maxValue替换掉,然后调整堆最大值的位置。

下面分别计算时间复杂度和空间复杂度。

时间复杂度                                    空间复杂度

方案一 O( n*lgn + k)          在栈中定义数组,几乎不占用堆内存
方案二 O(K + (n-k)*k)          在栈中定义数组,几乎不占用堆内存 
方案三 O(K + (n-k)*lgk)          O(k)

当n趋于无穷大的时候,很显然,方案三是最有选择,而且,当数据量非常的时候,方案一根本行不通,因为一个数组根本存不下海量数据,实际上,也几乎没有一个人这样写算法。快排的时间复杂度是n*lgn,如果把数据放入堆中,事实证明,在堆中对数据的操作,时间复杂度均为lgk,其中k为堆的容量。

这题两种思路,一种很直接的思路就快排,另一种是堆,我们来看下这两种算法的区别。第一种是快排,直接用快排将n个数排成有序,然后将前k大的数输出。平均时间复杂度为O(nlogn),空间复杂度为O(logn)。

当n很大时快排的时间也令人难以忍受,这时候可以考虑使用堆。
第二种是用一个大小为k的小根堆,先初始化为最小值(比n个数里面的任意值都小即可,这里初始为0),然后顺序遍历整个数组,如果大于堆顶元素则将其堆顶元素弹出并将其加入。平均时间复杂度O(nlogk),空间复杂度为O(k)。

//自己加测试代码即可,已经测过了,可运行!!!!!
 private static int partion(int[] array, int low, int high) {
        int mid = array[low];
        while (low < high) {
            while (low < high && array[high] <= mid)
                high--;
            array[low] = array[high];
            while (low < high && array[low] >= mid)
                low++;
            array[high] = array[low];
        }
        array[low] = mid;
        //请注意!!!!!,下里返回的值;表示它左边的小于它,右边的大于它。
        return low;
    }
    //这里是比较k和返回值的大小来判断一直循环这截至到top-k中的k!!!!!搞了4个小时!贝壳!!等我!!!!
 private static void top_k(int[] array, int k) {
        if (array == null || array.length == 0) {}        
        if (k < 0 || k > array.length - 1) {}      
        int low = 0, high = array.length - 1;
        int index = partion(array, low, high);
        while (index != k) {
            if (index > k) {
                high = index - 1;
                index = partion(array, low, high);
            } else {
                low = index + 1;
                index = partion(array, low, high);
            }
        }     
    }

这里可以加上剑指offer的第40题目。
4:从前端到后端,包括数据库整个的设计说一下(各种框架、解耦、缓存、消息队列的运用,还有数据库的索引优化)

这个结合自己的项目,总结项目。
5, rpc的过程说一下,有什么需要考虑的东西吗 ?

什么是RPC?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
AVA中几种常用的RPC框架介绍RPC是远程过程调用的简称,广泛应用在大规模分布式应用中,作用是有助于系统的垂直拆分,使系统更易拓展。Java中的RPC框架比较多,各有特色,广泛使用的有RMI、Hessian、Dubbo等。RPC还有一个特点就是能够跨语言,本文只以JAVA语言里的RPC为例。对于RPC有一个逻辑关系图,以RMI为例:
在这里插入图片描述

其他的框架结构也类似,区别在于对象的序列化方法,传输对象的通讯协议,以及注册中心的管理与failover设计(利用zookeeper)。
客户端和服务端可以运行在不同的JVM中,Client只需要引入接口,接口的实现以及运行时需要的数据都在Server端,RPC的主要依赖技术是序列化、反序列化和传输协议,JAVA里对应的就是对象的序列化、反序列化以及序列化后数据的传输。RMI的序列化和反序列化是JAVA自带的,Hessian里的序列化和反序列化是私有的,传输协议则是HTTP,Dubbo的序列化可以多种选择,一般使用Hessian的序列化协议,传输则是TCP协议,使用了高性能的NIO框架Netty。对于序列化,我还了解一些,像Google的ProBuffer、JBoss Marshalling和Apache Thrift等,之前有写一篇介绍ProBuffer的博文

1、RMI(远程方法调用)JAVA自带的远程方法调用工具,不过有一定的局限性,毕竟是JAVA语言最开始时的设计,后来很多框架的原理都基于RMI,RMI的使用如下:服务注册管理器写在了Server里,当然也可以抽出来单独作为一个服务,在其他一些框架中,往往用Zookeeper充当注册管理角色。

2、Hessian(基于HTTP的远程方法调用)基于HTTP协议传输,在性能方面还不够完美,负载均衡和失效转移依赖于应用的负载均衡器,Hessian的使用则与RMI类似,区别在于淡化了Registry的角色,通过显示的地址调用,利用HessianProxyFactory根据配置的地址create一个代理对象,另外还要引入Hessian的Jar包。
在这里插入图片描述

3、Dubbo(淘宝开源的基于TCP的RPC框架)基于Netty的高性能RPC框架,是阿里巴巴开源的,总体原理如下:

在这里插入图片描述
在了解Dubbo之前,要先对Zookeeper有深入的理解,当理解了zookeeper后,Dubbo也就了无秘密了。

6: redis的过期策略,为什么redis要用这样的过期策略(单线程,减少CPU负荷)
单线程的Redis为什么这么快

这个问题是对Redis内部机制的一个考察。根据我的面试经验,很多人都不知道Redis是单线程工作模型。所以,这个问题还是应该要复习一下的。

回答主要是以下三点:

纯内存操作


单线程操作,避免了频繁的上下文切换


采用了非阻塞I/O多路复用机制

什么是Redis? http://www.runoob.com/redis/redis-tutorial.html

Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。

在这里插入图片描述

Redis 与其他 key - value 缓存产品有以下三个特点:

Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。

Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。

Redis支持数据的备份,即master-slave模式的数据备份。

Redis 优势

性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。

Redis与其他key-value存储有什么不同?

Redis有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。

Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。

Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。

Redis作为一个高性能的内存NoSQL数据库,其容量受到最大内存限制的限制。

为了防止一次性清理大量过期Key导致Redis服务受影响,Redis只在空闲时清理过期Key。

1:访问Key时,会判断Key是否过期,逐出过期Key;
2:CPU空闲时在定期serverCron任务中,逐出部分过期Key;
3:每次事件循环执行的时候,逐出部分过期Key;

在这里插入图片描述

在这里插入图片描述

.7:手撕代码,有n个物品,每次最多拿100个,然后没走一步会掉一个,求走100米之后剩余的最大数量?
在这里插入图片描述

https://blog.csdn.net/qq_28439601/article/details/51986703

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值