.. | ||
maven | ||
pics | ||
src | ||
.gitignore | ||
javaCompile.sh | ||
make.sh | ||
README.md | ||
redis.md |
java 部分
java基础知识
-
面向对象的三大特征
- 继承:继承是类与类的一种关系,比较像集合中的从属于关系。
- 封装:隐藏类的基本信息,不允许外部程序直接访问,而是通过该类的方法实现对隐藏信息的操作和访问。
- 多态:方法的重写、重载与动态连接构成多态性;
-
面向对象的六大原则 【参考设计模式】
- 单一职责原理:一个类只负责一项职责。
- 里氏替换原则:劲量不要重写父类的已经实现了的方法,可以用接口等其他方法绕开。
- 依赖倒置原则:高层模块不应该依赖底层模块,二者应依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
- 接口隔离原则:客户端不应该依赖其他不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
- 迪米特法则:又叫做最小知道原则。就是一个类对自己依赖的类知道越少越好。
- 开闭原则:尽量通过扩展软件实体行为来实现变化。
-
数据类型
- 基本数据类型
- 数值类型
- 整型:int(4字节)、short(2字节)、long(8字节)、char(2字节)、byte(1字节)、
- 浮点型:float(4字节)、double(8字节)
- boolean: boolean(1字节)
- 数值类型
- 引用数据类型:数组、对象
- 强引用:用关键
new
出来的对象,强引用锁指向的对象在任何时候都不会被回收 - 软引用:用来描述有用但非必须的对象,在内存不足的时候可以回收
- 弱引用:用来描述非必须的对象,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发送之前。
- 虚引用:虚引用也称为幽灵引用或者幻影引用,它是最弱的一种引用关系。一个持有虚引用的对象,和没有引用几乎是一样的,随时都有可能被垃圾回收器回收。
- 强引用:用关键
- 基本数据类型
-
- Collection:集合类的根接口,list和set都继承自此接口
- List:有序,可以重复,一般用index标示顺序
- LinkedList:底层用双链表实现:增加删除效率高
- ArrayList:底层用数组实现:查找效率高
- Vector:实现了一个动态数组。和ArrayList相似,但是有以下不同:vector是同步的;
vector包含了许多传统方法,或者只是需要一个可以改变大小的数组的情况。
- Stack:先进后出
- set:无序,不能有重复的元素
- HashSet:HashSet不存入重复元素的规则.使用hashcode和equals
- LinkedHashSet:是对LinkedHashMap的简单包装,对LinkedHashSet的函数调用都会转换成合适的LinkedHashMap方法
- TreeSet:让存入的元素自定义比较规则;给TreeSet指定排序规则
- HashSet:HashSet不存入重复元素的规则.使用hashcode和equals
- Queue
- List:有序,可以重复,一般用index标示顺序
- Map:由键值对组成,和Collection完全不相干,是另一个接口
- Hashtable:同步的、线程安全的,不能接受为null的键值,不到万不得已不要使用。
- HashMap:非同步、线程不安全,一般不要求线程安全的情况下建议使用
- TreeMap:是一个有序的key-value集合,它是通过红黑树实现的。是SortedMap的一个实现类
- WeakHashMap:
- IdentifyHashMap:
- 并发集合类
- java.util.concurrent
- Executor:一个接口,其定义了一个接收Runnable对象的方法executor,其方法签名为executor(Runnable command),
- ExecutorService:是一个比Executor使用更广泛的子类接口,其提供了生命周期管理的方法,以及可跟踪一个或多个异步任务执行状况返回Future的方法
- Future:callable实现的存在返回值的并发编程
- CountDownLatch:可以用来在一个线程中等待多个线程完成任务的类
- Vector
- java.util.concurrent
- Collection:集合类的根接口,list和set都继承自此接口
-
- 根据处理数据的类型
- 字节流:字节流因为操作的是字节,所以可以用来操作媒体文件。
- 字符流:字符流中的对象融合了编码表,也就是系统默认的编码表。我们的系统一般都是GBK编码。字符流只用来处理文本数据,字节流用来处理媒体数据。
- 根据数据流向
- 输入流
- 输出流
- RandomAccessFile:
- 对象序列化
- 根据处理数据的类型
-
NIO(非阻塞IO)
-
AIO (异步IO)
-
多线程
- 多线程的实现方式
- 继承自Thread类(不能线程共享)
- 实现Runnable接口(不可以返回值)
- 实现Callable接口(可以抛出异常、返回值)
- ThreadPoolExecutor
- ThreadPoolExecutor的策略
- 线程数量未达到corePoolSize,则新建一个线程(核心线程)执行任务
- 线程数量达到了corePools,则将任务移入队列等待
- 队列已满,新建线程(非核心线程)执行任务
- 队列已满,总线程数又达到了maximumPoolSize,就会(RejectedExecutionHandler)抛出异常
- 常见四种线程池
- CachedThreadPool:线程数无限制;有空闲线程则复用空闲线程,若无空闲线程则新建线程;一定程序减少频繁创建/销毁线程,减少系统开销.
- FixedThreadPool:可控制线程最大并发数(同时执行的线程数);超出的线程会在队列中等待
- ScheduledThreadPool:支持定时及周期性任务执行。
- SingleThreadExecutor:有且仅有一个工作线程执行任务;所有任务按照指定顺序执行,即遵循队列的入队出队规则
- ThreadPoolExecutor的策略
- Executors
- 线程同步
- 同步方法:
- 同步代码块:synchronized 关键字在编译之后会在同步块的前后加上monitorenter和monitorexit,在执行monitorenter时,需要获取锁,如果占用所得对象是自己则需要将锁计数器加1,monitorexit时将锁计数器减1,如果为0则释放锁
- 关键字volatile:
- 防止指令重排
- 编译器重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序;
- 处理器重排序。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序;
- 实现可见性,不保证原子性
- 可见性:volatile保证线程所在空间中的volatile修饰的变量的值是最新的;
- 不保证原子性:两个线程对volatile修饰的变量同时进行赋值操作,可能导致两个线程对该变量进行一次赋值。
- 防止指令重排
- Reentrantlock:可重入锁,synchronized和Reentrantlock都是重入锁,区别如下:
- synchronized:
- 依赖JVM实现,加入偏向锁之后性能和Reentrantlock差不多了;
- 使用比较方便简洁,由编译器去实现加锁和释放;
- 只能是非公平锁;
- Reentrantlock:
- 主要依赖代码控制实现,可以避免进入内核态的阻塞;
- 需要手动加锁和释放锁,容易由于忘记释放锁导致死锁;
- 既可以是公平锁也可以是非公平锁;
- 提供Condition类,可以分组唤醒线程;
- 能够中断等待线程;
- synchronized:
- 使用局部变量实现线程的同步,如:ThreadLocal。
- 相关名词
- 对象锁、互斥锁、共享锁、公平锁、非公平锁(公平锁和非公平锁的比较)、
- 偏向锁:它会偏向于第一个访问锁的线程,如果在接下来的运行过程中,该锁没有被其他的线程访问,则持有偏向 锁的线程将永远不需要触发同步。如果在运行过程中,遇到了其他线程抢占锁,则持有偏向锁的线程会被挂起, JVM会尝试消除它身上的偏向锁,将锁恢复到标准的轻量级锁。引入偏向锁是为了在无多线程竞争的情况下尽量 减少不必要的轻量级锁执行路径。
- 原子操作、原子性、可见性
- 悲观锁和乐观锁
- 共享锁和排他锁
- 线程的交互
- notify()、 notifyAll()、wait()
- 多线程的实现方式
-
反射
java虚拟机
简述
java虚拟机我看过周志明的《深入理解java虚拟机》和周志明等人翻译的《java虚拟机规范(java SE 8版)》
结构
- 内存管理
- 虚拟机栈(非共享):
- 栈帧
- 局部变量表:局部变量数组包含了方法执行过程中的所有变量,包括 this 引用、所有方法参数、其他局部变量。
- 返回值:
- 操作数栈
- 类当前方法的运行时常量池引用
- 栈帧
- java堆(共享):堆包括:新生代( Eden、Survivor(from)、Survivor(to) )、老年代。
- 本地方法栈(非共享)
- 程序计数器(非共享)
- 方法区(共享):也可以说在堆中,方法区又叫非堆,用来区分对内存,在hotsport虚拟机中方法区又叫做永久带.用来存放类信息,常量等和类相关的数据.
- 元空间:1.8引入的,用来替换方法区(永久代);不再虚拟机中,使用的是本地内存,取决于电脑的内存大小
内存结构图
1.7及以前版本java内存分布图:
1.8 内存分布图:
- 虚拟机栈(非共享):
- 对象
- 对象的创建
- 对象的内存布局
- 对象头
- MarkWord:对象的MarkWord部分占4个字节,其内容是一系列的标记位,比如轻量级锁的标记位,偏向锁标记位等等。
- Class对象指针:其指向的位置是对象对应的Class对象(其对应的元数据对象)的内存地址.
- 实例数据:存放属性信息,包括父类的信息。
- 对齐填充(有些对象没有,具体不太懂):Java对象在内存中将以8字节对齐,也就是对象的总大小必须是8字节的整数倍。
- 对象头
- 对象的访问
- 垃圾回收
- 判断对象已死
- 引用计数法(无法判断循环引用的对象是否已死):每个对象都有一个引用计数器,对象每被引用一次就加1,对象被释放就减1,引用计数为0表示可以被回收。
- 可达分析法:如果对象能够到达root,就认为对象不可回收。root对象:
- 被启动类(bootstrap加载器)加载的类和创建的对象
- jvm运行时方法区类静态变量(static)引用的对象
- jvm运行时方法去常量池引用的对象
- jvm当前运行线程中的虚拟机栈变量表引用的对象
- 本地方法栈中(jni)引用的对象
- 垃圾收集算法
- 标记-清除算法(老年代,标记-清理算法容易产生碎片):标记阶段标记可回收的对象,请理阶段清理被标记的对象所占用的空间
- 复制算法(新生代,由于新生代对象存活较少,利用复制算法效率较高):按内存将容量将内存分为等大小的两块,每次只使用其中的一块,当一块的内存满了之后将存活对象复制到另一块上面去。
- 标记-整理算法(老年代):标记阶段标记可回收的对象,整理阶段将存活的对象移动到对象的另一边,清除边界以外的对象。
- 分代收集算法:新生代用复制算法(新生代存活的对象比较少),老年代用标记-清除和标记-整理算法
- 垃圾收集器(共六个垃圾收集器)
- 新生代收集器(新生代收集器一般都利用复制算法)
- Serial收集器(复制算法)
- ParNew收集器(复制算法)
- Parallel Scavenge收集器(复制算法)
- 老年代收集器
- Serial Old 收集器(标记-整理算法)
- CMS收集器(标记-清除算法): 初始标记、 并发标记、 重新标记、 并发清除
- Parallel Old 收集器(标记-整理算法)
- G1收集器
- 步骤 : 初始标记、 并发标记、最终标记、筛选标记
- 特点: 并行与并发、分代收集、空间整合、可预测停顿
- 新生代收集器(新生代收集器一般都利用复制算法)
- 判断对象已死
- class 文件
- class文件的结构
- 魔数:判断class文件是否被虚拟机接受的Class文件,魔术固定值是0xCAFEBABE
- 版本号(主版本号、次版本号):主板本和副版本共同构成了Java文件的格式版本
- 访问标志(标识一些类或者接口的访问信息):用于表示某个类或者接口的访问权限及基础属性
- 类索引(this_class):this_class的值必须是对constant_pool表中项目的一个有效索引值,表示这个Class文件所定义的类或接口。
- 父类索引(super_class):对于类来说,super_class的值必须为0或者是对constant_pool表中项目的一个有效索引值。
- 接口数/接口表:
- 字段计数器:它用于表示该类或接口声明的类字段或者实例字段。
- 常量池计数器:constant_pool_count的值等于constant_pool表中的成员数加1。
- 常量池(主要存放两大类常量),常量池的索引范围是1至constant_pool_count−1。
- 字面量
- 符号引用
- 字段表集合(含有字段访问标志)
- 方法数/方法表:
- 属性数/属性表:
- class文件的结构
- 类加载机制
- 类加载过程
- 加载
- 链接
- 验证:
- 准备:为类变量等赋初始值。如:
public static int a = 123;
初始值为0,不是123. - 解析:将符号引用转化为直接引用的过程。
- 初始化
- 使用
- 卸载
- 双亲委派模型
- 启动类加载器:加载
${JAVA_HOME}/jre/lib/
下面的jar包,所有以java.*
的class都是由启动类加载器加载的。 - 扩展类加载器:加载
${JAVA_HOME}/jre/ext/*.jar
- 应用程序类加载器:用户指定的类。
- 用户自定义类加载器:
- 启动类加载器:加载
- 破坏双亲委派模型
- 线程上下文类加载器
- 类加载过程
- 虚拟机字节码执行引擎(这部分还没有看懂,就不具体列提纲了) *
- 高效并发
- 内存间的交互
- lock(锁定):作用于主存的变量
- unlock(解锁):作用于主存的变量
- read(读取):作用于主存的变量
- load(载入):作用于工作内存的变量
- use(使用):作用于工作内存的变量
- assign(赋值):作用于工作内存的变量
- store(存储):作用于工作内存的变量
- write(写入):作用于主存的变量
- 内存间的交互
算法部分
简述
java部分我主要看过《剑指offer》和《程序员面试金典》两本书。感觉两本书都挺不错的。
《 剑指offer》
《 程序员面试金典》
面试考题型目录
脚本
脚本compile.sh 没有完成