1. 创建Thread的方式:继承Thread类,重写run方法;实现Runable接口,重写run方法。
2. 实现了或继承了Collection接口的是List、Set、Queue
3. 多态表现形式是重写
4. java数据库连接库JDBC用到了桥接模式
5. try{}catch{}会增加额外的开销
6. 子类可以访问父类受保护的成员
7. .接口中声明的'变量'必须为public final static,所以为常量
8. File类能够存储文件属性、建立文件、能够获取文件目录信息
9. String split 方法默认返回一个数组,如果没有找到分隔符,会把这个字符串当成一个长度为1的字符串数组返回到结果。
10. 只要没有定义任何构造函数,JVM才会为类生成一个默认的构造函数
11. 只有调用thread.start才是开启新线程,thread.run其实是执行普通的run方法
12. static可以用来修饰内部类,但是不能修饰外部类,外部类的修饰只能是public、abstract、final。
13. JAVA的跨平台特性是因为JVM的存在,它可以执行.class字节码文件,而不是JAVA源代码
14. java.util.Collection 是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式。
java.util.Collections 是一个包装类。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。
15. OutputStream实现了Closeable和Flushable接口,具有flush方法。flush方法强制将缓冲区中的字符流、字节流输出,目的是如果输出流输出到缓冲区完成后,缓冲区没有填满,那么缓冲区会一直等待被填满,所以在关闭输出流之前要调用flush()
16. 触发Full GC条件:
1. 老年代满
2. 持久代满
3. System.gc()
17. wait()和join()会使线程释放锁资源
18. ThreadLocal :```public class ThreadLocal ```
采用哈希表的方式来为每个线程都提供一个变量的副本
保证各个线程间数据安全,每个线程的数据不会被另外的线程访问和破坏。
19. 线程安全:喂,sshe:Vector、Stack、StringBuffer、hashtable、enumeration
20. Java一律采用Unicode编码方式,每个字符无论中文还是英文字符都占用2个字节。
21. 子类不能继承父类的构造方法,只能调用父类的构造方法。
22. 类与类、类与接口、接口与接口
1. 类与类之间的关系为继承,只能单继承,但可以多层继承
2. 类与接口之间的关系为实现,既可以单实现也可以多实现
3. 接口与接口之间的关系为继承,既可以单继承,也能多继承
23. J2EE中,当把来自客户机的HTTP请求委托给servlet时,会调用HttpServlet的service方法。
24. 进程间的通信方式:
1. 管道:类似于缓存,一个进程把数据放在某个缓冲区域,等另一个进程拿,管道式单向传输的。效率低下
2. 消息队列:也类似缓存。如果a进程发送数据占用内存大且两个进程之间通信频繁,不适用。发送消息(拷贝)耗费时间多。
3. 共享内存:解决拷贝消耗时间,系统加载进程,分配给进程的不是实际物理内存,而是虚拟内存,可以让两个进程拿出一块虚拟地址,映射到相同物理内存中;虽然有独立的虚拟内存空间,但确是相同物理内存。
4. 信号量。共享内存会有线程安全问题。信号量本质是计数器。信号量初始值为1,A访问时,信号量为0,此时B访问,发现为0,说明有进程访问,那么B就无法访问。
5. Socket:远距离通信。
25. 操作系统管理内存:
1. 段式存储管理:
每个段由0到最大的线性地址序列构成。各个段的长度可以是0到某个允许的最大值之间的一个数。不同的段的长度可以不同(通常情况下也都不一样),段的长度在运行期间可以动态改变。
段式存储管理下的逻辑地址组成格式为(s,o),s为段号,o为段内偏移量。段号和对应内存中的物理地址由段表记录。寻址时,先根据段号到段表中查询物理起始地址(基址),然后加上偏移量,得到最终的物理地址
2. 页式存储管理
物理页帧:把物理地址空间分成大小相同的基本单位。大小为2^n,
逻辑页面:把逻辑地址空间划分为相同大小的基本单位
页帧大小和页面大小必须一致
26. 堆的特点是根节点的值最大(最小),且根节点的两棵子树也是一个堆。由于堆的这个特性,常用来实现优先队列,堆的存取是随意的。
27. 常见的查找算法:顺序查找、折半查找、分块、B树、Hash表
28. JAVA实现线程安全的单例:饿汉式、枚举、双重检验锁。
29. 单例和静态方法的区别:
1. 静态需要不停的初始化释放,占用资源。
2. 单例可以被实例化,方法可以重写,比较灵活;
3. 静态方法不需要实例化,不会在堆内存占用空间。
1. 首先明确一下,静态成员并不是什么程序加载时创建并初始化的,而是类加载时进行。类的加载是第一次真正用到它的时候(拿类new实例或调用它的静态方法)进行的,而这个加载过程需要将 class 文件中构成类的静态和实例方法等类的成员的字节码指令一同加载到内存中,而后要为静态域分配存储空间并使用静态块对其进行初始化(如果有的话)。在上面例子中,类加载后,所有成员(包括fun和staticfun)的字节码指令均在内存中了,随时等待着调用,并且静态域 s 所占用的存储空间也用空引用初始化好了。
2. 从内存上来看,当第一次调用 getInstance() 方法时会创建此类的唯一实例(所谓的单例出现),其实也可以在声明 s 时 new 它的唯一实例,将实例化延后是为了避免类加载后实例使用前内存的浪费。
3. 静态方法线程是安全的,所谓线程安不安全是指当多个线程同时操作一个对象(通过调用它的实例方法)时是否会造成对象内部状态的破坏,而静态方法不是用来对实例进行操作的,所以一般不用考虑线程同步。如果在静态方法中读写文件,此时如果多个线程同时通过调用此静态方法对文件操作肯定会造成文件内容的破坏,但这不是线程没同步造成的,因为没有对象的状态被破坏。但可以利用线程同步机制防止上面情况的发生。
4.从生命周期上来看,静态方法的类会在代码编译的时候就被加载,静态方法中产生的对象,会随着静态方法执行完毕而释放掉,而且执行类中的静态方法时,不会实例化静态方法所在的类。如果用单例模式, 产生的那一个唯一的实例,会一直在内存中,不会被GC清除的(原因是静态的属性变量不会被GC清除),除非整个应用退出了JVM (所以实际应用中更多的是静态方法中获取单例)
5. 单例模式是利用唯一的实例保存系统的状态,提供的实例方法也是为了对这个唯一的实例进行操作,而静态方法多是一些工具方法,Math 类中的静态方法就是一个典型的例子,如果仅仅是想不自己创建类的实例就可以调用到某些方法来完成一定的操作,那完全没必要也不应该使用单例模式。
6. 从执行效率上看: 静态方法与实例方法,在加载时机和占用内存上,静态方法和实例方法是一样的,在类型第一次被使用时加载。调用的速度基本上没有差别。 但是从日志打印来看,个人感觉还是静态方法在执行效率上快一点。
7. 静态方法是面向过程的,而非面向对象的编程思想
30. 如果已经commit了某代码,现在你对改代码做了一点点修改,你又不想再全部commit一遍,可以通过 ```git commit -amend```
31. URL长度最长为20
32. 为什么Redis是单线程的?
因为Redis是基于内存的操作,CPU不是Redis 的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就采取单线程。
33. Redis怎么实现分布式锁?
Redis利用Redis中的set实现分布式锁。
34. Redis持久化机制
持久化流程:
1、客户端向服务器发送写操作(数据在客户端的内存中)
2、数据库服务端收到写请求数据(数据在服务端的内存中)
3、服务端调用write,将数据卸载磁盘上(数据在系统内存的缓冲区中)
4、操作系统将缓冲区中的数据转移到磁盘控制器中(数据在磁盘缓存中)
5、磁盘控制器将数据写到磁盘的物理介质中(数据真正落到磁盘上)
1. RDB
把数据以快照的形式保存在磁盘中
在指定的时间间隔内将内存中的数据集快照写入磁盘。默认的持久化方式。默认文件名为dump.rdb
触发机制(三种):
save触发:阻塞当前Redis。
bgsave(background save):异步执行快照,同时还可以响应客户端请求
自动触发:通过配置文件完成。
缺点:容易丢失数据
2. AOF
把每条收到的写命令通过write追加到文件中。
三种触发机制:
每修改同步always:每次修改都会立即记录到磁盘,性能差,但是数据完整性好
每秒同步everysec:异步操作。每秒记录,一秒内宕机->数据丢失
不同步no:从不同步
缺点:相比RDB,日志文件大;AOF开启后,支持的写QPS比RDB的低;以前AOF发生过bug,通过AOF记录日志,进行数据恢复时,没有恢复一模一样的数据。
35. 破坏双亲委派模型
1. 自定义类加载器,重写loadClass方法。
2. 使用线程上下文类加载器(Thread Context ClassLoader)
36. 双亲委派模型三次破坏史
1. JDK1.2引入双亲委派模型,而类加载器和抽象类在JDK1.0已经存在,有的用户已经自定义类加载器。
2. 基础类调用回用户的代码,引进线程上下文类加载器(Thread Context ClassLoader)
3. 用户追求程序动态性
4. Redis的Cluster 提供的分区数量有限,一致性较弱,既不是CP,也不是AP。Redis的集群,并不能达到分布式系统的理论极限,只为了获得一定的真实世界性能。
37. select、poll、epoll之间的区别
1. select时间复杂度为O(n),poll时间复杂度为O(n),epoll时间复杂度为O(1);
2. select 适合少量活跃连接,一般几千;epoll适合大量不太活跃的连接
如果有大量活跃连接可以使用多线程+select;
38. 分布式环境下,分库分表后如何生成全局唯一的主键id?
1. 新建一台专门用于创建id的数据库
全局范围新增一台数据库,专门用于创建提供主键。其他表创建之前,首先向这台服务器插入数据,通过主键自增方式获取id,再插入到自己的数据表中。
缺点:1、需要额外创建数据库实例2、请求压力大,无法满足高并发场景
适用于写请求并发小,写入数据量较大场景。
2. 使用uuid
使用version1的uuid,基于当前时间戳,随机数及机器的MAC地址共同获取一个尽可能唯一的字符串作为主键id
优点:使用方便,无需额外部署服务器
缺点:生成随机字符串过长,若使用mysql的innodb,不适合作为主键id
3. 系统当前时间
获取系统当前时间,换算成时间戳,作为主键id
缺点:高并发下,同一秒甚至同一毫秒可能产生多个写请求,此时生成的主键id必然重复
改进:将系统时间戳与业务id、文件id拼接
4. snowflake算法
---
![image-20200829100614735](C:\Users\SenseChuang\AppData\Roaming\Typora\typora-user-images\image-20200829100614735.png)
![image-20200829100621658](C:\Users\SenseChuang\AppData\Roaming\Typora\typora-user-images\image-20200829100621658.png)
---
![image-20200829150109976](C:\Users\SenseChuang\AppData\Roaming\Typora\typora-user-images\image-20200829150109976.png)
dst = new String(src,"GBK").getBytes("UTF-8");
---
![image-20200829150236163](C:\Users\SenseChuang\AppData\Roaming\Typora\typora-user-images\image-20200829150236163.png)
采用xml实现数据的交换
---
![image-20200829154436216](C:\Users\SenseChuang\AppData\Roaming\Typora\typora-user-images\image-20200829154436216.png)
---
![image-20200829160623015](C:\Users\SenseChuang\AppData\Roaming\Typora\typora-user-images\image-20200829160623015.png)
doGet/doPost是在javax.servlet.http.HttpServlet中实现的。
---
![image-20200829164629766](C:\Users\SenseChuang\AppData\Roaming\Typora\typora-user-images\image-20200829164629766.png)
---
![image-20200829201829464](C:\Users\SenseChuang\AppData\Roaming\Typora\typora-user-images\image-20200829201829464.png)
---
java的Arrays.sort:判断数组长度是否大于286,如果是,再判断是否小于47,如果是,使用插入排序,如果大于47小于286使用快速排序;如果大于286且具有结构,使用归并排序;如果大于286却不具有结构:则根据长度是否小于47,采取插入排序或快速排序
---
一键复制
编辑
Web IDE
原始数据
按行查看
历史