春江花月夜-张若虚
春江潮水连海平,海上明月共潮生。滟滟随波千万里,何处春江无月明!江流宛转绕芳甸,月照花林皆似霰。空里流霜不觉飞,汀上白沙看不见。江天一色无纤尘,皎皎空中孤月轮。江畔何人初见月?江月何年初照人?人生代代无穷已,江月年年望相似。不知江月待何人,但见长江送流水。白云一片去悠悠,青枫浦上不胜愁。谁家今夜扁舟子?何处相思明月楼?可怜楼上月裴回,应照离人妆镜台。玉户帘中卷不去,捣衣砧上拂还来。此时相望不相闻,愿逐月华流照君。鸿雁长飞光不度,鱼龙潜跃水成文。昨夜闲潭梦落花,可怜春半不还家。江水流春去欲尽,江潭落月复西斜。斜月沉沉藏海雾,碣石潇湘无限路。不知乘月几人归,落月摇情满江树。
这道面试题你确定不看看吗:一条sql语句,有多个查询条件,你会选择哪个字段作为索引,为什么?
每个面试题都是一个知识点,无论面不面试,都应该看看,掌握之后也是可以运用到开发中的,而且每个知识点都会衍生出很多问题,会的越多,掌握的知识点就越多,正所谓:不积跬步无以至千里,不积小流无以成江河…
今天的题目是:在mysql中,一条sql,有多个查询条件,你会选择哪个字段作为索引,依据是什么?
sql示例是这样的:
select * from table where field_a = xx and field_b = xx and field_c = xx
思考一下,如果是你,你会选哪个字段作为索引,为啥那,如果你一点思路没有,就且听我慢慢道来…
这个回答的时候,蒙肯定是不行的,你选择field_a字段肯定要把理由说出来,如果说不出来,直接说不会也要好过瞎蒙,起码留给面试官一个不会就是不会,不瞎蒙的印象 这都不知道,还说你会mysql
解题:
首先说索引,表中创建索引的目的是为提供更高效的查询,既然是提高效率,肯定是有高效的索引和低效的索引的区分,这道题其实也是说选择哪个字段作为索引会提供更高效的查询。
为了循序渐进的剖析这个问题,我创建一个测试表 test,表中插入十万条测 ...
zookeeper命令详解
ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby一个开源的实现。它提供了简单原始的功能,分布式应用可以基于它实现更高级的服务,比如分布式同步, 配置管理, 集群管理, 命名管理,队列管理。它被设计为易于编程,使用文件系统目录树作为数据模型
特点1、 最终一致性: client 不论连接到哪个 Server,展示给它都是同一个视图,这是 ZooKeeper最重要的性能。
2、 可靠性:具有简单、健壮、良好的性能,如果消息 m 被到一台服务器接受,那么它将被所有的服务器接受。
3、 实时性: ZooKeeper 保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。
但由于网络延时等原因, ZooKeeper 不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在
读数据之前调用 sync()接口
4、 等待无关(wait-free):慢的或者失效的 client 不得干预快速的 client 的请求,使得每个client 都能有效的等待
5、 原子性:更新只能成功或者失败,没有中间状态6 ...
【数据结构】| 二分查找
二分查找是一种效率较高的查找方法,时间复杂度是O(logn)
二分查找:每次都通过跟区间中的中间元素对比,将待查找的区间缩小为一半,直到找到要查找的元素,或者区间被缩小为0
使用前提:
二分查找必须依赖顺序表结构(数组)
二分查找查询的数据必须是有序的
关于查询数据的大小,如果查询的数据太小,直接遍历就可以,两者效率相差不大,如果要查找的数据太大,因为二分查找必须依赖顺序表结构,所以需要申请的空间必须是连续的,有可能会出现没有足够的连续内存空间的情况
实现:
数组arr:{1,4,7,8,12,43,56,87,98,323,3545,5685},利用二分查找返回数组下标
例:查找43输出5
public static int binary(int[] arr, int n){
int start = 0;
int end = arr.length - 1;
while (start<=end){
int mid = (start + end)/2;
if(arr[mid]== n){
retur ...
【jvm】类加载机制
虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型
类的生命周期加载,验证,准备,解析,初始化,使用,卸载七个阶段,其中验证,准备,解析三个部分统称为链接
加载,验证,准备,初始化和卸载这5个阶段的顺序是固定的,为了支持动态绑定,解析这个过程可以发生在初始化阶段之后
加载阶段加载阶段,主要完成以下3件事情:
通过“类全名”来获取定义此类的二进制字节流
将字节流所代表的静态存储结构转换为方法区的运行时数据结构
在java堆中生成一个代表这个类的java.lang.Class对象,作为方法区这些数据的访问入口
加载阶段完成后,虚拟机外部的二进制字节流就按照虚拟机所需的格式存储在方法区之中,方法区中的数据存储格式有虚拟机实现自定义
验证阶段验证阶段是为了确保class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全
文件格式验证
基于字节流验证,验证字节流是否符合Class文件格式的规范,并且能被当前虚拟机处理
元数据验证
基于方法区的存储结构验证,对字节码描述信息进行语义验证 ...
【jvm】垃圾收集器
在了解垃圾收集算法之后,我们要看一下基于垃圾收集算法实现的垃圾收集器是如何实现的,本文出现的垃圾收集器都是HotSpot虚拟机提供的实现
堆内存是垃圾收集器主要回收垃圾对象的地方,堆内存可以根据对象生命周期的不同细分为新生代和老年代,每个年代都可以选择适合的垃圾收集算法,新生代使用复制算法,老年代使用标记清除或者标记整理算法
HotSpot虚拟机提供了7种垃圾收集器,其中适用于新生代的三种,老年代的三种,还有一种新生代老年代都适用
新生代垃圾收集器:Serial收集器,ParNew收集器,Parallel Scavenge收集器
老年代垃圾收集器:Serial Old收集器,Parallel Old收集器,CMS收集器
都适用的收集器:G1收集器
所有垃圾收集器组合情况如下:
图中连线的收集器表明可以一起搭配使用
Serial 收集器Serial收集器曾是jdk1.3之前新生代收集器的唯一选择,串行收集器,单线程工作,所以效率高,但是会产生Stop The World,适用于堆内存比较小的时候使用,使用复制算法回收垃圾对象
参数设置:-XX:+UseSerialGC 使用Seri ...
【jvm】内存区域
jvm在执行的过程中会把它所管理的内存划分为若干个不同的数据区域,这些数据区域中,有些依赖着用户线程的启动和结束而建立和销毁,有些则随着jvm进程的启动而创建
内存区域jvm的运行数据区域可以分为两种:线程私有和线程共享
线程私有: 每个线程的私有数据,包括: 程序计数器、java虚拟机栈、本地方法栈
线程共享: 所有线程共享的部分,包括: Java 堆、方法区、常量池
jvm内存区域划图示
运行时数据区域程序计数器程序计数器是较小的内存空间,它可以看做是当前线程所执行的字节码的行号指示器,用来执行选取小一条需要执行的字节码指令,属于线程私有的内存
如果执行的是一个java方法,这个计数器记录的是正在执行的虚拟机字节码指令地址,如果执行的是Native方法,这个计数器值为空
虚拟机栈虚拟机栈,也是线程私有的,它的生命周期与线程相同,每个方法在执行时都创建一个栈帧,每个方法从调用到执行完成,对应着一个栈帧的入栈到出栈
虚拟机栈描述的是java方法执行的动态内存模型
栈帧存储的数据包括: 局部变量表,操作数栈,动态链接,方法出口等信息
在虚拟机栈中,规定了两种异常:
当栈调 ...
【jvm】GC与垃圾回收算法
GCGrabage Collection GC 垃圾收集,在了解了jvm的内存区域之后,要关心的问题就是垃圾收集了,因为我们的内存是有限的,程序在运行中会不断的产生新的对象占用内存空间,所以我们需要一个垃圾收集机制去回收内存
在java内存运行时区域的各个部分,其中程序计数器,虚拟机栈,本地方法栈三个区域随着线程的创建而创建,销毁而销毁,栈中的每个栈帧分配多少内存基本上在类结构确定下来是就抑制了,所以这几个区域不需要过多考虑回收的问题,方法结束或者线程结束,内存自然就回收了,而在堆和方法区这两块区域中,我们只有在程序运行期间才能知道会创建哪些对象,这部分内存的分配合回收都是动态的,所以我们主要关注点在如果进行回收堆内存和方法区这两块区域的垃圾内存
对象是否存活垃圾收集,我们首先要判断哪些对象是垃圾的对象
引用计数算法:每个对象都添加一个引用计数器,当有地方引用它的时候,计数器就加1,当引用失效的时候计数器就减1,这样通过这个引用计数器就可以知道当前对象是否被引用,但是这种方式的弊端就是无法解决循环引用的问题,假如a持有b的引用,b持有a的引用,两个对象的计数器都是1,但是a和b这两个对 ...
java反射
在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。对于任何一个对象,我们都能够对它的方法和属性进行调用。我们把这种动态获取对象信息和调用对象方法的功能称之为反射机制。
反射中常用的到的类
Class类: 代表类的实体,在运行的Java应用程序中表示类和接口
Field类: 代表类的属性
Method类: 代表类的方法
Constructor类: 代表类的构造方法
Class类
Class对象的由来是将class文件读入内存,并为之创建一个Class对象
Class类表示正在运行的java应用程序中的类和接口,也就是jvm中有N多的实例每个类都有该Class对象,包括基本数据类型
package com.my.concurrent.reflect;
import org.springframework.util.StringUtils;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* @au ...
java包装类的缓存机制
java 包装类的缓存机制,是在Java 5中引入的一个有助于节省内存、提高性能的功能,只有在自动装箱时有效
Integer包装类
举个栗子:
Integer a = 127;
Integer b = 127;
System.out.println(a == b);
这段代码输出的结果为true
使用自动装箱将基本类型转为封装类对象这个过程其实底层实现是调用封装类的valueOf方法:
Integer a =127; 相当于 Integer a = Integer.valueOf(127);
看一下Integer的valueOf方法:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
如果入参 i 大于等于IntegerCache.low或者 ...