zl程序教程

您现在的位置是:首页 >  其他

当前栏目

面试错题库

面试 题库
2023-09-11 14:16:29 时间

设计模式的六大原则
1代码可重用性
2可读性
3可扩展性
4可靠性
5使程序呈现高内聚,低耦合的特性
1、单一职责原则(Single Responsibility Principle)
单一职责原则表示一个模块的组成元素之间的功能相关性。从软件变化的角度来看,就一个类而言,应该仅有一个让它变化的原因;通俗地说,即一个类只负责一项职责。
2、开放封闭原则(Open Close Principle)
开闭原则的意思是:对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。
3、里氏代换原则(Liskov Substitution Principle)
里氏代换原则是面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP 是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。里氏代换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
4、依赖倒转原则(Dependence Inversion Principle)
这个原则是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。
5、接口隔离原则(Interface Segregation Principle)
这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。它还有另外一个意思是:降低类之间的耦合度。由此可见,其实设计模式就是从大型软件架构出发、便于升级和维护的软件设计思想,它强调降低依赖,降低耦合。
6、迪米特法则(Demeter Principle),又称“最少知道原则”
最少知道原则是指:一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立。
7、合成复用原则(Composite Reuse Principle)
合成复用原则是指:尽量使用合成/聚合的方式,而不是使用继承。
redis的数据类型以及应用场景
1string
a可以用于高频率访问的信息,比如微博粉丝数、关注数等等,使用用户主键作为key
2hash
ahash类型很像对象的数据存储形式,可以灵活的添加删除对象的属性
b可以实现抢购、发放优惠券、激活码之类的业务场景,使用商家主键作为key、商品的主键作为field、发放的数量作为value
3list
a保存多个数据,底层是双向链表的存储结构实现,是按进入存储空间的顺序进行区分
b可以实现朋友圈点赞与取消点赞的业务场景,还有像微博关注列表,需要按照用户的关注顺序来进行展示
4set
a能够存储大量的数据,在查询方面有非常高的效率,且数据不能重复
b可以实现随机推荐之类的业务场景,如热点歌单推荐、热点新闻推荐,还有共同好友,某个公众号有多少个朋友关注,以及黑名单白名单等等
5sorted set
a底层是基于set结构的,所以数据不能重复
b可以实现排行榜、消息通知先后顺序、微信消息列表排序等业务场景
redis的持久化机制
1RDB持久化机制,对redis中的数据执行周期性的持久化
2AOF机制对每条写入命令作为日志,以append-only的模式写入一个日志文件中,在redis重启的时候,可以通过回放AOF日志中的写入指令来重新构建整个数据集
3如果同时使用RDB和AOF两种持久化机制,那么在redis重启的时候,会使用AOF来重新构建数据,因为AOF中的数据更加完整
什么是进程,什么是线程
1进程是指在系统中正在运行的一个应用程序,程序一旦运行就是进程。一个进程可以拥有多个线程,每个线程使用其所属进程的栈空间。
2线程是进程的一个实体,是进程的一条执行路径。线程是CPU独立运行和独立调度的基本单位。
什么是多线程
多线程是指从软件或者硬件上实现多个线程的并发技术
多线程的好处:
1使用多线程可以把程序中占据时间长的任务放到后台去处理,如图片、视屏的下载;
2发挥多核处理器的优势,并发执行让系统运行的更快、更流畅,用户体验更好;
多线程的缺点:
1大量的线程降低代码的可读性;
2更多的线程需要更多的内存空间;
3当多个线程对同一个资源出现争夺时候要注意线程安全的问题;
什么是CAS?
多线程的实现方式?
线程的三大特性
1原子性:一个操作或者多个操作,要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行
2可见性:当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看的到修改的值
3有序性:程序执行的数序顺序按照代码的先后顺序执行,如使用线程中join()来实现
线程的五大状态?生命周期?
1新建状态:新建线程对象,并没有调用start()方法之前
2就绪状态:调用start()方法之后线程就进入就绪状态,但是并不是说只要调用start()方法线程就马上变为当前线程,在变为当前线程之前都是为就绪状态。值得一提的是,线程在睡眠和挂起中恢复的时候也会进入就绪状态哦。
3运行状态:线程被设置为当前线程,开始执行run()方法。就是线程进入运行状态
4阻塞状态:线程被暂停,比如说调用sleep()方法后线程就进入阻塞状态
5死亡状态:线程执行结束
线程池的作用、好处
池化的思想主要是为了减少每次获取和结束资源的消耗,提高对资源的利用率。比如在一些偏远地区打水不方便的,大家会每段时间把水打过来存在池子里,这样平时用的时候就直接来取就好了。
好处:
1降低资源消耗:通过重复利用现有的线程来执行任务,避免多次创建和销毁线程。
2提高相应速度:因为省去了创建线程这个步骤,所以在拿到任务时,可以立刻开始执行。
3提供附加功能:线程池的可拓展性使得我们可以自己加入新的功能,比如说定时、延时来执行某些线程。
什么是多线程死锁?产生的条件是什么?
锁的类型
1、公平锁/非公平锁
1公平锁是指加锁前检查是否有排队等待的线程,优先排队等待的线程,先来先得 。
2非公平锁加锁时不考虑排队等待问题,直接尝试 CAS 获取锁,获取不到自动到队尾等待。
3非公平锁性能比公平锁高 5~10 倍,因为公平锁需要在多核的情况下维护一个队列
4Java 中的 synchronized和ReentrantLock 默认的 lock()方法采用的是非公平锁。
2、可重入锁
1可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,在进入内层方法时会自动获取锁。
2对于Java ReentrantLock而言,他的名字就是ReentrantLock重新进入锁。
3对于Synchronized而言,也是一个可重入锁。
4可重入锁的一个好处是可一定程度避免死锁。
3、独享锁/共享锁
1独享锁是指该锁一次只能被一个线程所持有。共享锁是指该锁可被多个线程所持有。
2对于Java ReentrantLock、Synchronized而言,是独享锁。但是对于Lock的另一个实现类ReadWriteLock,其读锁是共享锁,其写锁是独享锁。
3读锁的共享锁可保证并发读是非常高效的,读写,写读 ,写写的过程是互斥的。
4、互斥锁/读写锁
1上面讲的独享锁/共享锁就是一种广义的说法,互斥锁/读写锁就是具体的实现。
2互斥锁在Java中的具体实现就是ReentrantLock
3读写锁在Java中的具体实现就是ReadWriteLock
5、乐观锁和悲观锁
1乐观锁认为对于同一个数据的并发操作,是不会发生修改的。在更新数据的时候,会采用不断更新的方式更新数据。乐观的认为,不加锁的并发操作是没有问题的。
2悲观锁认为对于同一个数据的并发操作,一定是会发生修改的,哪怕没有修改,也会认为修改。因此对于同一个数据的并发操作,悲观锁采取加锁的形式。悲观的认为,不加锁的并发操作一定会出问题。
3乐观锁适合“读”操作非常多的场景,不加锁会带来大量的性能提升。而悲观锁适合“写”操作非常多的场景,
6、分段锁
1分段锁其实是一种锁的设计,并不是具体的一种锁,对于ConcurrentHashMap而言,其并发的实现就是通过分段锁的形式来实现高效的并发操作。
2分段锁的设计目的是细化锁的粒度,就数组而言,当操作不需要更新整个数组的时候,就仅仅针对数组中的一项进行加锁操作。
7、偏向锁/轻量级锁/重量级锁
1这三种锁是指锁的状态,并且是针对Synchronized。
2偏向锁是指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁。降低获取锁的代价。
3轻量级锁是指当锁是偏向锁的时候,被另一个线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,提高性能。
4重量级锁是指当锁为轻量级锁的时候,另一个线程虽然是自旋,但自旋不会一直持续下去,当自旋一定次数的时候,还没有获取到锁,就会进入阻塞,该锁膨胀为重量级锁。重量级锁会让其他申请的线程进入阻塞,性能降低。
8、自旋锁
1如果持有锁的线程能在很短时间内释放锁资源,那么那些等待竞争锁的线程就不需要做内核态和用户态之间的切换进入阻塞挂起状态,它们只需要等一等(自旋), 等持有锁的线程释放锁后即可立即获取锁,这样就避免用户线程和内核的切换造成的消耗。
同步锁与lock锁的区别以及应用场景
1Lock是一个接口,而synchronized是Java中的关键字;
2synchronized当一个线程获取了对应的锁,并执行该代码块时,其他线程便只能一直等待,等待获取锁的线程释放锁,不能够响应中断,这样的好处是不会导致死锁现象发生;
3Lock锁,可以让等待的线程只等待一定的时间或者响应中断。但Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时必须在try{}catch{}块中进行,需要在finally块中释放锁;
4在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时,此时Lock的性能要远远优于synchronized。
5在并发量比较小的情况下,使用synchronized是个不错的选择,但是在并发量比较高的情况下,其性能下降很严重,此时ReentrantLock(可重入锁,唯一实现了Lock接口的类)是个不错的方案。
集合的区别
1List:有序集合,元素可重复,可以插入null,常用的实现类有 ArrayList、LinkedList、Vector
2Set:无序集合,元素不重复,可以插入一个null,常用的实现类有HashSet、LinkedHashSet、TreeSet
3Map:键值对集合,键和值都是无序的,可以有一个null键和随意的null值,常用的实现类有HashMap、LinkedHashMap、Hashtable、TreeMap
hashMap和hashTable的区别
1二者都实现了Map接口,HashMap继承自AbstractMap类,Hashtable继承自Dictionary类,Dictionary类是一个已经被废弃的类
2HashMap线程不安全效率高,HashTable线程安全效率低
3HashMap是没有contains方法的
4Hashmap是允许key和value为null值的
ArrayList和LinkedList的区别
1ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2对于随机访问get和set,ArrayList优于LinkedList,因为LinkedList要移动指针。
3对于新增和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据。
session和cookie的区别
1HTTP:超文本传输协议,是无状态协议,它不能以状态来区分和管理请求和响应。也就是说,服务器单从网络连接上无从知道客户身份,所以需要给客户端们颁发一个通行证,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份了。这就是Cookie的工作原理。
2cookie数据存放在客户的浏览器上,session数据放在服务器上
3cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,如果主要考虑到安全应当使用session
4session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,如果主要考虑到减轻服务器性能方面,应当使用cookie
5单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的cookie不能3K
6将登陆信息等重要信息存放为session;其他信息如果需要保留,可以放在cookie中
InnoDB与MyISAM的区别以及应用场景
1InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度;
2InnoDB支持外键,MyISAM不支持。对一个包含外键的InnoDB表转为MYISAM会败;
3InnoDB是聚集索引,使用B+Tree作为索引结构,数据文件是和(主键)索引绑在一起的(表数据文件本身就是按B+Tree组织的一个索引结构),必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。
aMyISAM是非聚集索引,也是使用B+Tree作为索引结构,索引和数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。
b也就是说:InnoDB的B+Tree主键索引的叶子节点就是数据文件,辅助索引的叶子节点是主键的值;而MyISAM的B+树主键索引和辅助索引的叶子节点都是数据文件的地址指针。
4InnoDB支持表、行(默认)级锁,而MyISAM支持表级锁。InnoDB的行锁是实现在索引上的;
1MyISAM管理非事务表。它提供高速存储和检索,以及全文搜索能力。如果应用中需要执行大量的SELECT查询,那么MyISAM是更好的选择。
2InnoDB用于事务处理应用程序,具有众多特性,包括ACID事务支持。如果应用中需要执行大量的INSERT或UPDATE操作,则应该使用InnoDB,这样可以提高多用户并发操作的性能。
什么是B+Tree?
什么是事务?
事务的传播机制
事务的特性
1 、原子性
事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做
2 、一致性
事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。如果数据库系统 运行中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是不一致的状态。
3 、隔离性
一个事务的执行不能其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。
4 、持久性
指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响。
事务的隔离级别
第一种隔离级别:Read uncommitted(读未提交)
如果一个事务已经开始写数据,则另外一个事务不允许同时进行写操作,但允许其他事务读此行数据,该隔离级别可以通过“排他写锁”,但是不排斥读线程实现。这样就避免了更新丢失,却可能出现脏读,也就是说事务B读取到了事务A未提交的数据
解决了更新丢失,但还是可能会出现脏读
第二种隔离级别:Read committed(读已提交)
如果是一个读事务(线程),则允许其他事务读写,如果是写事务将会禁止其他事务访问该行数据,该隔离级别避免了脏读,但是可能出现不可重复读。事务A事先读取了数据,事务B紧接着更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。
解决了更新丢失和脏读问题
第三种隔离级别:Repeatable read(可重复读取)
可重复读取是指在一个事务内,多次读同一个数据,在这个事务还没结束时,其他事务不能访问该数据(包括了读写),这样就可以在同一个事务内两次读到的数据是一样的,因此称为是可重复读隔离级别,读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务(包括了读写),这样避免了不可重复读和脏读,但是有时可能会出现幻读。(读取数据的事务)可以通过“共享读镜”和“排他写锁”实现。
解决了更新丢失、脏读、不可重复读、但是还会出现幻读
第四种隔离级别:Serializable(可序列化)
提供严格的事务隔离,它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行,如果仅仅通过“行级锁”是无法实现序列化的,必须通过其他机制保证新插入的数据不会被执行查询操作的事务访问到。序列化是最高的事务隔离级别,同时代价也是最高的,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻读
什么是脏读什么是幻读
1脏读:所谓的脏读,其实就是读到了别的事务回滚前的脏数据。
2幻读:事务A首先根据条件索引得到N条数据,然后事务B改变了这N条数据之外的M条或者增添了M条符合事务A搜索条件的数据,导致事务A再次搜索发现有N+M条数据了,就产生了幻读。
3不可重复读:事务A首先读取了一条数据,然后执行逻辑的时候,事务B将这条数据改变了,然后事务A再次读取的时候,发现数据不匹配了,就是所谓的不可重复读了。
表分区与分表的区别
1表分区:是指根据一定规则,将数据库中的一张表分解成多个更小的,容易管理的部分。从逻辑上看,只有一张表,但是底层却是由多个物理分区组成。
2分表:指的是通过一定规则,将一张表分解成多张不同的表。比如将用户订单记录根据时间成多个表。
3分表与分区的区别在于:分区从逻辑上来讲只有一张表,而分表则是将一张表分解成多张表。
视图的优缺点
视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据。但是,视图并不在数据库中以存储
的数据值集形式存在。行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成。
优点:
1第一个显著优点就是它简化了操作。此时我们完全不用关心视图是怎么处理数据的,我们只需要知道如何使用这个结果集即可,视图相当于一个中间层。
2第二个显著优点就是它更加安全。比如我们可以让用户有权去访问某个视图,但是不能访问原表,这样就可以起到保护原表中某些数据的作用。
3第三个显著优点就是降低耦合。假如我们以后要修改原表的结构,那么我们可以通过修改视图的定义即可,而不用修改表结构。
缺点:
1性能:从数据库视图查询数据可能会很慢,特别是如果视图是基于其他视图创建的。
2表依赖关系:将根据数据库的基础表创建一个视图。每当更改与其相关联的表的结构时,都必须更改视图。
MySQL内外连接的区别
MySQL索引的优缺点
MySQL索引什么时候会失效
MySQL的行锁、表锁、页锁
1、行级锁
行级锁是 MySQL 中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突,其加锁粒度最小,但加锁的资源消耗也最大。
特点:
资源消耗大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
2、表级锁
表级锁是 MySQL 中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分 MySQL 引擎支持。最常使用的 MyISAM 与 InnoDB 都支持表级锁定。
特点:
资源消耗小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低。
3、页级锁
页级锁是 MySQL 中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。因此,采取了折衷的页级锁,一次锁定相邻的一组记录。BDB 支持页级锁。
特点:
开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
●MyISAM 和 Memory 采用表级锁(table-level locking)
●BDB 采用页级锁(page-level locking)或表级锁,默认为页级锁;
●InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁。
●InnoDB 中的行锁与表锁
update和delete哪个执行快?为什么?
百万级数据表怎么设计
SpringMVC八大注解
Spring循环依赖注入
Spring BeanFactory与FactoryBean有什么区别?
git代码冲突



如果本文对你有帮助,别忘记给我个3连 ,点赞,转发,评论,

咱们下期见!答案获取方式:已赞 已评 已关~

学习更多知识与技巧,关注与私信博主(03)